The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


THE PSION SIBO HARDWARE DEVELOPMENT KIT 


Version 1.00 


May 26 1995 


Revision 1.00 Page i 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


(c) Copyright Psion PLC 1990-93 


All rights reserved. This manual and the programs referred to herein are copyrighted works of Psion 
PLC, London, England. Reproduction in whole or part, including utilisation in machines capable of 
reproduction or retrieval, without express written permission of Psion PLC, is prohibited. Reverse 
engineering is also prohibited. 


The information in this document is subject to change without notice. 


Psion and the Psion logo are registered trademarks, and Psion, Psion MC, Psion HC, Psion Series 3, 
Psion Series 3a and Psion Workabout are trademarks of Psion PLC. 


TopSpeed is a registered trademark of Clarion Software Corporation. Intel 8086 and 80286 are 
registered trademarks of Intel Corporation. IBM, IBM XT and IBM AT are registered trademarks of 
International Business Machines Corp. Microsoft and MS-DOS are registered trademarks of 
Microsoft Corporation. Apple and Macintosh are registered trademarks of Digital Equipment 
Corporation. Brief is a registered trademark of Underware Inc. Psion PLC acknowledges that some 
other names referred to are registered trademarks. 


Revision 1.00 Page ii 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Contents 


‘ 
De IMGrOMUCUON sec ioiciescccetisshicattxstcathaslicatixssdcstenslacatenstecatenslicatinssdesvenslacevinswdvatensldcsvisatibiteislacibedse 


2. System Overview..........scccccscssccssssscscsscsseccsscssecssccsesssscssesssscsssesscssesssssesssscssssssscssssssscsessssesesseeees 


3. Hardware Overview .........sssccssssssssssscssscssscsssssssesssesssesssesssesssssssssessscssscsssessesssesssnssseesscseoeeees 
The Psion SIBO serial protocol .... 
Psion ASICs and what they do.. 
Interrupts . 
The current range of Psion periphera 


4. The Psion SIBO Serial Protocol . 
Hardware Interface ... 
The Physical layer . 
The Transport layer .. 


5. Mechanical Overview ...........sscssscsssssrscsssssessscessecssessessssesseessessscesssessesscssssssscsssessccssesssessosees LD 
The Psion Series 3/3a range ... 
The Psion Workabout 
The Psion HC range 


6. ASIC 4......... 
ASIC4 Addressing and Modes 
Reset and configuration 
ASIC4 Pin-out 


7. ASIC 5.......scesee 
ASICS Mode 
Reset and configuration 
ASICS Pin-out 


8. Example Peripheralls................cccssccssssssssssssseccsscscccssssscsssscccesssscscesssssesssscsssssssssesscsssssscsseeesess OO 
The ASIC4 Example Interface Board.. 
The Psion 3-Link 


9. Device Driver Overview...........cccsrsercesssserscersserecssecssesscesssesesssessssessesssesscsscssscsssssssesssessosees OT 
Introduction 
Device Names and Channel: 
Loadable Logical Device Driver Structure 
Mandatory LDD Functions ............... 
Interrupts and Interrupt Service Routines at 
Loadable Physical Device Driver Structure... ccscecesesesseesssesssesesssesesesescseseseenenesesesesesesenenesseesesesusueasaeaeseeessecacaeaeaeenenssesecasaseeeeeneeeeeaeaes 


10. ASIC4/ASIC5 Based Device Drivers 


Introduction 
SIBO Hardware Expansion Channels 
Talking to ASIC4.. 
ASIC4 Registers 
Talking to ASICS .. 
ASICS Registers... 
Communicating with ASIC4 
Sending and Receiving data using ASIC4. 
Obtaining and using a channel... 
Controlling ASICS's UART 
Hold and Resumes. 
Example Device Driver: 


11. An Example Device Driver for ASIC4: A4EXIF.LDD.. 


Introduction 


oo TO eR UU RS gs pad 


Mandatory LDD Function: 
The Non-Mandatory LDD Functions..........cceee 
The handling of synchronous and asynchronous I/O 
Interrupts and Interrupt Service Routines 
Other important local device driver functions 
Structures and Include files «0... cee 


12. An Example Device Driver for ASIC5: SYS$AS5.PDD.............ssssssssssssssessessessssesscsessessesseee 77 


Introduction 
The LDD-PDD interface. 


13. Debugging and Testing Device Drivers 
Introduction .... 
Debugging Techniqu 
Further Testing Strategies ae 
Memory Lestitng seiscs lech easch oiece siscn Sates losecdestecwcsautsse sean tosevaleslosedtracepudtesiiensdertoanioenteoisebeensse bait es ieettaus adanus teats a a tanta eae 


APPENDIX: Source Code Files.. 
A4EXIF.ASM oo 
SYS$AS5.ASM .... 102 
Assembler Macros. 1S 


Revision 1.00 


Page iii 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


1. INTRODUCTION 


This document is intended to provide guidance to anyone wishing to construct peripherals for the 
Psion SIBO (sixteen bit organiser) range of computers. It describes in detail all aspects of Psion 
peripheral hardware development and the structure of the software required to drive such peripherals. 
It is the aim of this document to aid third party development engineers in producing production ready 
peripherals for any of the following Psion products: Series 3/3a, Workabout, HC and HCDOS. 
Mechanical and plastic moulding information and information on how to develop production test 
equipment is therefore also included. The emphasis throughout is on the two key Psion peripheral 
chips ASIC4 and ASIC5. Detailed information regarding their functionality is provided. The 
structure of Psion hardware device drivers is examined both in general outline and then with regard to 
two specific examples whose source code is provided in the appendix to this document. It has been 
assumed that the reader has some knowledge of a Psion computer such as the Series 3/3a and an 
understanding of how such a machine is programmed. A good understanding of electronics, the C 
programming language and 8086 assembler is also assumed. 


Due to the continuous nature of development, information in this manual may change without notice. 


Developers are advised to contact Psion Support to confirm critical details prior to committing 
products to manufacture. 


Revision 1.00 Page | of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


2. SYSTEM OVERVIEW 


All present Psion computers are based around the proprietary SIBO architecture. A SIBO machine is 
a battery-powered, 8086-based, computer system. SIBO stands for SIxteen Bit Organiser. The 
architecture has been designed with the size, weight and power consumption of computers designed 
for the portable environment in mind. The key components of the SIBO architecture are: 


e —_ An 8086 class processor . 

e A sophisticated power management system that selectively powers subsystems under software 
control. 

e — Asynchronous, high speed, serial protocol (the Psion SIBO serial interface) for communication 
between a machine and its peripherals. 

e —_ Solid State Disks (SSDs) that provide fast, low-power, silicon-based mass storage with no 
moving parts. 

e Hardware protection of the system from aberrant software processes (trapping of out of range 

addressing and a watch-dog timer on interrupts being disabled). 

Real-time clock. 

ROM-resident system software. 

Graphics LCD display. 

A touch sensitive digitising pad that provides a pointing device (only available on some models). 

ISDN-8bit standard combo sound system (only available on some models). 


The SIBO architecture has primarily been implemented in custom ICs called ASICs. At the time of 
writing there are ten different SIBO ASICs. Some of these ASICs have been designed for use inside 
peripherals and these will discussed in detail throughout this document. All SIBO ASICs have been 
implemented in surface mount packages and are based on a static CMOS technology. Current SIBO 
products in the MC, HC and Series 3 range are based on the same three principal chips. These are 
the V30H (an 8086-compatible processor) and two Psion custom chips known as ASIC1 and ASIC2. 
Later SIBO products including the Series 3a and Workabout have these three devices integrated into a 
single Psion custom chip known as ASIC9. The V30H is an enhanced 16-bit CMOS version of the 
8088 found in the original IBM PC. It is software compatible with the 8088. The V30H is a fully 
static design which means that all the internal storage elements (i.e. its registers) are made from static 
rather than dynamic storage components. This in turn means that there is no minimum clock speed 
required to refresh the storage elements and the system clock can be stopped at any time with no loss 
of internal state. This technique is used extensively in the SIBO architecture to save power while the 
processor is idle (i.e. waiting for an event). 


The Psion SIBO serial protocol is a proprietary synchronous two wire serial standard by which host 
Psion handhelds communicate with external devices. These devices will typically be Memory Packs 
(usually referred to as Solid State Disks or SSDs), RS232 and Centronics printer interfaces, fax 
modems, bar-code scanners, and so on. The SIBO architecture provides for two basic forms of 
expansion device, namely the extended internal expansion connection (as with SSDs) and the reduced 
external expansion connection (the 6-pin S3a serial port or the 11-pin LIF connector). The MC and 
HC range of computers have two SSD ports and two separate independent single row 25-way 
extended internal expansion ports. These ports have in addition to a Psion SIBO Channel, direct, 
parallel I/O from the processor. Direct connection to these machines 7.2 volt battery is included to 
support high power peripherals such as Printers and Barcode readers. The Series 3 range of 
computers have two ports for SSDs and a single, reduced, 6-pin expansion port, which provides only a 
Psion SIBO serial channel and limited power (<25mA). The Psion Workabout has two SSD ports, 
two internal expansion points, and one external expansion port. The single external expansion port 
uses an | 1-pin Low Insertion Force (LIF) socket which provides a Psion SIBO channel, 25mA of 
current and additional lines required for detecting the presence of the Workabout cradle. Each 
internal expansion port consists of a single row 26-way connector carrying two high speed serial 
ports. 


Revision 1.00 Page 2 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


A range of Psion peripherals have been produced for connection to the Psion handhelds outlined 
above. These peripherals currently incorporate one of two custom integrated circuits (ASIC4 and 
ASICS) that convert SIBO serial protocol signals to data bus TTL level voltages which enable 
memory and memory-mapped peripherals to be addressed. ASIC4 is used in SSDs and for memory- 
mapped peripherals. A typical ASIC4 peripheral for a Psion S3a would consist of an ASIC4 
connected to port C of the host machine and a peripheral chip/device mapped into ASIC4's addressing 
space. ASICS is a general purpose I/O chip with a UART on board that can be run in several 
different modes. For example ASICS can be used for MCRs (magnetic card readers) or Centronics 
interfaces thereby simplifying peripheral design. Psion extended internal expansion ports carries an 
active low interrupt input line to the host controller circuitry. The reduced external expansion ports 
has an active high interrupt input line. The function of the interrupt can thus be programmed into the 
host machine's ASIC1 or ASIC9. 


The low-level programming interface to a Psion handheld peripheral is encapsulated within an 
appropriate device driver. Psion device drivers are written in 8086 assembler and follow a prescribed 
pattern outlined later in this document. The construction of a peripheral and the coding of its 
complimentary device driver enable the developer to access its functionality through the means of 
library calls in a C program. Examples of such calls are p_loadldd(), p_open() and p_close(). 
I/O requests are routed through the device driver's strategy vector which maps to the PLIB p_iow () 
call. The device driver is built using the Borland Turbo Assembler and resides in a single code 
segment. The device driver can be stored in either RAM or a ROM on board the peripheral or can be 
supplied on an SSD (solid state disk). 


Revision 1.00 Page 3 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


3. HARDWARE OVERVIEW 


The Psion SIBO serial protocol 


The Psion SIBO serial protocol is a general purpose method of bi-directional serial data transfer. It 
has been designed for synchronous communication between a host controlling device and a number of 
slave devices. On a hardware level, the SIBO serial protocol is implemented through Psion ASICs. 
The controlling device must contain an ASIC2 (or ASIC9) and the slave devices an ASIC4 or ASICS. 
The various Psion ASICs are described in more detail below. 

The synchronous SIBO serial protocol interface consists of 2 wires: 

CLK ~ - Aclock output from the controller to the slaves. Nominally 3.84 MHz. 

DATA - A bi-directional synchronous data line. 

The data is transferred using a series of 12 bit frames including 8 data bits each. This equates to a 
theoretical maximum data transfer rate of approximately 312 Kbytes/second. Other bits of the frame 
contain control information. The "system" is generically defined by 2 protocol layers, namely the 
Physical layer and the Transport layer. These layers are described in detail in the next chapter. 


Psion ASICs and what they do 


ASIC stands for Application Specific Integrated Circuit and as previously indicated, these devices are 
widely used within Psion hardware. Summaries of the functionality of each ASIC that is relevant to 
peripheral development are presented below: 


ASIC1: ASIC1 is the main system controller chip for the SIBO architecture. It connects directly to 
the 8086-based processor (i.e. the V30H) controlling all bus cycles to and from the processor. This 
configuration effectively forms a micro-controller like device that executes 8086 instruction codes. 
ASIC 1 is made up of a number of functional blocks including a bus controller, a programmable 
timer, an eight input interrupt controller, an LCD controller and the memory decoding circuitry. 


ASIC2: ASIC2 is the peripheral controller chip for the SIBO architecture. It contains the system 
clock oscillator and controls switching between the standby and operating states. ASIC2 provides an 
interface to the power supply, keyboard, buzzer and SSDs. ASIC 2 includes the eight-channel SIBO 
serial protocol controller and provides interface circuitry to both the reduced external and extended 
internal peripheral expansion ports. 


ASIC4: ASIC4 is a serial protocol slave IC for addressing memory and general memory-mapped 
peripherals. It is used in SSDs to convert SIBO serial protocol signals into addresses within the 
memory range of the memory pack. ASIC4 was designed to be a cut-down version of ASICS which 
was the original SIBO serial protocol slave chip. 


ASICS: ASICS is a general purpose I/O chip with a built-in UART that can be set to run in a number 
of different modes thereby simplifying the task of peripheral design. For example, it is possible to set 
up ASICS to run as a Centronics parallel port interface, an 8-bit parallel I/O port, a serial bar code 
controller or a serial RS232 converter. 


ASIC9: ASIC9 is a composite chip comprising of a V30H processor, ASIC1, ASIC2 and general I/O 
and PSU control logic all on one IC. ASIC9 thus integrates all the digital logic required to produce a 
SIBO architecture computer less the memory onto one chip. ASIC9 has a few additional features 
such as an extra free-running clock (FRC) and a codec interface for sound. 


Revision 1.00 Page 4 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Interrupts 


Psion peripherals usually incorporate some circuitry to generate hardware interrupts. Both reduced 
external expansion ports (such as the LIF connector on the Workabout or the 6-pin serial port 
connector on the S3a) and extended internal expansion ports (such as the two single row 25-way HC 
connectors) carry an interrupt line. This is an active high input to the host machine's interrupt 
controller circuitry which resides on the logical equivalent of ASIC1. The OS intercepts all interrupts 
and can be requested to call a particular function within a controlling device driver. Eight hardware 
interrupts are supported by SIBO hardware. IRQO is the highest priority and IRQ7 the lowest. All 
interrupts are level triggered and must be serviced in the following order: 

e Device asserts the appropriate interrupt request line. 

e The interrupt controller unit within either ASIC2 or ASIC9 places onto the data bus the vector of 
the highest priority device with an interrupt pending. This enables the CPU to jump to the 
correct interrupt service routine code. 

e During the interrupt service routine, the software clears the interrupt line by some action specific 
to the device. 

e The interrupt service routine then informs the interrupt controller that the interrupt has been 
cleared by writing to the non-specific end of interrupt (NSEOD) location. 

e If another interrupt is pending then go back to the second step. 

With 8086-based processors, it is not possible to have nested interrupts. 


The current range of Psion peripherals 


There are currently a number of Psion peripherals in use and some of the key ones are outlined below 
in order to provide the developer with a feel for peripheral design issues: 

SSDs: Solid State Disks (or Memory Packs) use a built-in ASIC4 to decode SIBO serial protocol 
signals into memory addresses within the memory range of the SSD. 

Psion 3-link: The 3-link translates the high speed SIBO serial protocol channel on the S3a 6-pin 
reduced external expansion socket into a serial RS232 format. This enables the host machine to 
communicate with a PC for example by means of connecting the 3-link unit from the handheld's 6-pin 
port to the PC's COM1 or COM2 port. The 3-link contains an ASICS which uses its on-board UART 
to convert SIBO serial protocol signals to RS232 format TTL level voltages. 

The HC Printer: The HC Printer translates SIBO serial protocol signals transmitted across the single 
row 25-way extended internal expansion socket of the host HC into a parallel 8-bit format that is 
compatible with the universal Centronics printer interface standard. The HC Printer unit contains an 
ASICS running in Centronics interface mode which acts as the serial protocol slave and requires a 
small number of support chips. 

Psion 3-Fax: The 3-Fax contains an ASIC4 and a memory-mapped modem chip set which permits the 
host machine to transmit (but not receive) fax messages. 

Barcode: The Psion Barcode reader employs an ASICS running in serial mode to read the data 
received from the barcode decoder chip into a SIBO serial protocol format that can be transmitted to 
the host ASIC2/ASIC9. 

Workabout RS232 Interface: This peripheral connects to the single row 26-way extended internal 
expansion port of the Workabout. It incorporates an ASICS running in its default mode to translate 
SIBO serial protocol signals into a TTL level (+/-5v) serial RS232 format using ASIC5's on-board 
UART. The TTL level RS232 signals are converted into the standard EIA format (+/-12v) before 
coming out on the conventional RS232 9-pin D-type connector. 


Revision 1.00 Page 5 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


4. THE PSION SIBO SERIAL PROTOCOL 


Introduction 


The Psion SIBO serial protocol is a proprietary standard for bi-directional serial data transfer between 

a controlling device and a number of slave devices. The synchronous interface consists of 2 wires 

CLK and DATA as mentioned earlier: 

CLK _~ - Aclock output from the controller to the slaves. Nominally 3.84 Mhz for memory 

interfaces or 1.536.Mhz continuous for peripherals. 

DATA - A bi-directional synchronous data line. 

The data is transferred using a series of 12 bit frames including 8 data bits each. This equates to a 

theoretical maximum data transfer rate of approximately 312 Kbytes/second. Other bits of the frame 

contain control information. The "system" is generically defined by 2 protocol layers:- 

e The Physical layer defining the hardware interface and frame structure. 

e The Transport layer defines system control and register transfers between the controller and the 
slaves. 

Using this system, a large number of higher level implementations can be defined. In normal use the 

controller will communicate to slaves in a point to point configuration. Multidrop configurations with 

a number of slaves attached to one channel of the controller are also supported. 


As indicated in the previous chapter, the SIBO serial protocol controller circuitry resides in either an 
ASIC2 or an ASIC9 depending on the particular Psion hardware platform. The S3a and Workabout 
employ ASIC9 whereas the HC, MC and S3 use ASIC2. 


Hardware Interface 


As indicated above, the SIBO serial protocol consists of two lines that switch at 5V CMOS voltage 
levels: 


Clock Line 


This line is used to synchronously clock data between the controller and slaves. It is always output 
from the controller circuitry that resides in ASIC2/ASIC9. The clock should only be active during the 
transfer of data or when the serial channel is continuous clocking mode (used by ASICS). At all other 
times it is tri-state pulled low. 


Clock Timing Parameters 


Parameter 
Width of Clock High 


Width of Clock Low 
Cycle time of clock 
Clock Frequency 


Data Line 


This is a bi-directional line used to transfer data synchronously between the controller and slaves. 
The direction of the data line is not determined by the physical layer but by the control information in 
the transport layer. This is described in the next section. When no data transfers are in progress the 
data line is always set to input on both the controller and slaves. This line is pulled low. Data is 
changed on the falling edge of clock by the transmit device and latched into the receiving device on 
the rising edge of the clock. 


Revision 1.00 Page 6 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The Physical layer 


This section specifies the low level protocol of the SIBO serial protocol. The physical layer protocol 
consists of a series of 12 bit frames. There are four types of frames:- 

Null frames - Transmitted by controller to synchronise slaves. 

Control frames - Control information transmitted by controller to slaves. 

Data output frames - Data frame transmitted by controller to slaves. 

Data input frames - Data frame received by controller from a slave. 


Frame structure 


All 12 bit frames have the following structure:- 


Bit 

Name ST 

ST Start bit. This bit goes high to indicate the start of a valid frame. 

CTL ~~ Control bit. When low indicates this is a control frame. High indicates a data frame. 
Il Idle bit. Used to turn around direction of data line. Normally Low. 

DO-D7 Data bits. 

12 Idle bit. Used to turn around direction of data line. Normally low. 

Null Frame 


This is a special frame transmitted by the controller to ensure all slaves are synchronised. It is 
generated by transmitting 12 clock pulses with the data line set to input. Since the data line is pulled 
low this results in 12 zeroes being transmitted. 


Control frame 


This frame is transmitted from the controller to one or more slaves. The data line is an output from 
the controller throughout the whole frame. The bits in the frame have the following value in a control 
frame: 


ST Start bit. This bit goes high to indicate the start of a valid frame. 
CTL Control bit. Low to indicate this is a control frame. 

I1 Idle bit Set low. 

DO-D7 Data bits. 8 bits of control information. 

I2 Idle bit Set low. 


Data Output Frame 


This frame is transmitted from the controller to one or more slaves. The data line is an output from 
the controller throughout the whole frame. The bits in the frame have the following value in a data 
output frame: 


ST Start bit. This bit goes high to indicate the start of a valid frame. 
CTL Control bit. High to indicate this is a data frame. 

Il Idle bit Set low. 

DO-D7 Data bits. 8 bits of transmitted data. 

12 Idle bit Set low. 


Data Input Frame 


This frame is received by the controller from a slave. The data line is an output from the controller 
for cycles 1 and 2 and input to the controller for cycles 4 to 11. The bits in the frame have the 
following value in a data input frame: 


ST Start bit. Output from controller. This bit goes high to indicate the start of a valid 
frame. 

CTL Control bit. Output from controller. High to indicate this is a data frame. 

Il Idle bit. Used to turn around direction of data line. Both controller and slave 

should tri-state the data line during this bit. This bit should be low due to pull 

down resistor on data line. The controller changes the data line from output to 


Revision 1.00 Page 7 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


input at the end of cycle 2. The slave changes the data line from input to 
output at the start of cycle 4. 


DO-D7 Data bits. Output from slave 8 bits of data transmitted by slave. Controller sets data 
line to input during these bits. 

12 Idle bit. Used to turn around direction of data line. Both controller and slave 

should tri-state the data line during this bit. Should be low due to pull down 

resistor on data line. The slave changes data line from output to input at the end of 
cycle 11. 


Data line direction 


The following table summarises the direction of the data line. 


CONTROLLER SLAVE 
Condition CK DATA CK 


Outside Frame 

Null frame 

Control Frame 

Data output from controller 

Data input to controller:- 
Cycles 1-2 
Cycle 3 
Cycles 4-11 
Cycle 12 


OO000 0004 


Key T Tri-state 
I Input 
O Output 


The Transport layer 


This section specifies the transport level protocol that operates above the SIBO serial communication 
physical layer. The transport layer protocol controls the serial communication between the SIBO 
Protocol Controller (SPC) and a number of SIBO Protocol Slave (SPS) devices. The following rules 
apply:- 

1) The interface is controlled by the writing of control bytes from the controller to the slaves. Control 
bytes cannot be written by the slaves. 

Unsolicited data cannot be sent from the slave to the controller. 

2) The controlling device contains two registers to communicate to the slaves. These are the control 
register (byte, write only) and the Data register (byte or word, read/write). 

Control bytes are transmitted to the slaves by writing to the control register. 

The format of the control byte is as follows:- 


The control word can have 2 distinct formats depending on the setting of bit 7 the Select (S) bit:- 
Select = 0 This is the slave select mode. This mode is for selecting, deselecting and resetting slaves. 
Select = 1 This is the slave control mode. This mode is for communicating with a slave which has 
been previously selected using the select slave command. 


Revision 1.00 Page 8 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Slave select mode 


The format of the slave select byte is as follows:- 


Key:- 
R single reset bit. 
TU 6 bit ID field. 


The 6 bit ID field is a property only of the slave. No slave may have an ID of zero, hence there can be 
63 different slaves connected to one controller. The reset bit (R) controls whether the slave(s) are 
selected or reset. If R = 0 slave(s) are reset, R = | slave(s) are selected. Slave select control bytes can 
be summarised by the following table:- 


Description 
Reset all slaves 


Reset specific slave with ID = xx 
Deselect slave (does not reset slave) 
Select slave with ID=xx and read slave info (see below). 


The Reset function is dependant on the slave. It would normally put the slave into a known passive 
reset state. 

Select Slave with ID=xx (S=0,R=1) 

This is a special command that causes a slave with ID=xx to transmit to the controller an 8 bit 
information field. This field depends entirely on the slave but must be non zero. A reply of 0 
indicates that there is no slave of the requested ID present. 


Slave control mode 


This mode is for communicating with a slave which has been previously selected using the select 
slave command described above. 
The format of the control word in slave select mode is as follows:- 


R/W Read/write select. 0 = write, 1 = read 

B/W Data transfer size. 0 = 1 byte transfer, 1 = word (2 byte transfer). 
S/M Single/Multi transfer mode. 0 = single, 1 = multibyte. 

XXXX = 4 bits of data to slave. 


Note the meaning of the 4 bits of data (XX XX) is entirely dependent on the slave. 


The settings of R/W,B/W,S/M bits in the control word determine the size, type and direction of 
subsequent data transfers in the following manner:- 


Revision 1.00 Page 9 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


R/W B/W _ S/M 

0 0 0 write a single byte to slave 

0 0 1 write a number of single bytes to slave 

0 1 0 write a byte pair to slave (not implemented) 

0 1 1 write a number of byte pairs to slave (not implemented) 

1 0 0 read a single byte from slave 

1 0 1 read a number of single bytes from slave 

1 1 0 read a byte pair from slave (not implemented) 

1 1 1 read a number of byte pairs from slave (not implemented) 
Write a single byte 


This command readies the currently selected slave to receive a byte of data and sets up the controller 
so that the next byte (or the LSB of a word) written to its data register will be transmitted to that 
slave. Anything further written to the controller's data register will have no effect. 


Write a number of single bytes 


This command readies the currently selected slave to receive a number of sequential bytes of data. 
The slave will expect to receive data bytes until another control byte is received. The controller is set 
up so that the next byte (or the LSB of a word) written to its data register will be transmitted to that 
slave. All subsequent bytes written to the controller's data register will be transmitted to the slave. 
This will continue until another byte is written to the controller's control register. 


Write a byte pair 


This command readies the currently selected slave to receive two bytes of data and sets up the 
controller so that the next word written to its data register will be transmitted to that slave (LSB first). 
Anything further written to the controller's data register will have no effect. 


Write a number of byte pairs 


This command readies the currently selected slave to receive a number of sequential byte pairs of 
data. The slave will expect to receive byte pairs until another control byte is received. The controller 
is set up so that the next word written to its data register will be transmitted to that slave (LSB first). 
All subsequent words written to the controller's data register will be transmitted to the slave. This 
will continue until another byte is written to the controller's control register. 


Read a single byte 


This command triggers a byte to be transmitted from the selected slave to the controller. This byte 
can then be read from the LSB of the controller's data register. Further reads of the controller's data 
register will return the same data but have no effect on the protocol. 


Read a number of single bytes 


This command triggers a byte to be transmitted from the selected slave to the controller. This byte 
can then be read from the LSB of the data register. This read will trigger the next byte to be 
transmitted to the data register of the controller. All subsequent reads of the controller's data register 
will trigger further bytes to be transmitted to the controller. This will continue until another byte is 
written to the controller's control register. 


Read a byte pair 

This command triggers a byte pair to be transmitted from the selected slave to the controller. This 
word can then be read from the controller's data register. Further reads of the controller's data 
register will return the same data but have no effect on the protocol. 

Read a number of byte pairs 


This command triggers a byte pair to be transmitted from the selected slave to the controller. This 
word can then be read from the controller's data register. This read will trigger the next byte pair to 


Revision 1.00 Page 10 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


be transmitted to the data register of the controller. All subsequent reads of the controller's data 
register will trigger further byte pairs to be transmitted to the controller. This will continue until 
another byte is written to the controller's control register. 


Timing 
The time taken for commands to be processed and data sent is shown below. The time is given in 


SIBO pack protocol clock cycles. The length of a clock cycle is nominally 260 nanoseconds for a 
clock frequency of 3.84 MHz. 


Receive and process the control byte 12 cycles 
Byte transfer to or from slave 12 cycles 
Byte pair transfer to or from slave 24 cycles 


When writing to the controller's data and control registers the following rules apply:- 

e After writing to the control register there must be a delay of at least 12 cycles before the data 
register is accessed or another control word is written. 

e Toread a word from the data register after the command to read byte pair is issued there must a 
delay of at least 12 (for control byte)+24 (for the byte pair transfer)= 36 cycles. 

e To perform a multiple byte pair write there must be a delay of at least 12 cycles after the 
command is written to the control register before the first word can be written to the data register 
and a delay of at least 24 cycles between subsequent writes to the data register. 


States 

A slave can be in one of 5 states. Note a control byte can be received and interpreted at any time. 
1) Waiting to receive a data byte or control byte 

2) Waiting to receive a data byte pair or control byte 

3) Waiting to transmit a data byte or control byte 

4) Waiting to transmit a data byte pair or control byte 

5) Waiting to receive control byte only 


Revision 1.00 Page 11 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


5. MECHANICAL OVERVIEW 


This section will contain information regarding mechanical and plastic moulding for Series 3/3a, 
Workabout and HC machines that is deemed to be of especial importance to developers who are 
considering producing peripherals for these particular Psion platforms. 


The Psion Series 3/3a range 


S3a/Series 3 Reduced External Expansion Port 


The Psion Series 3/S3a personal digital assistants have two SSD slots and provide access to external 
peripheral units through a single reduced internal expansion port, port C, on the left edge of the 
machine. The reduced external serial interface expansion port from the Series 3/3a forms six wires. 
The purpose of each is described in the table below. In addition to data, clock and power an active 
high interrupt line is provided. This allows the peripheral device to generate an interrupt within the 
host series 3/3a. The level of interrupt that is generated depends on both the machine and the 
expansion port that is used. Either ASIC4 or ASICS can act as the other end of the Psion Serial 
Interface. With exception of the interrupt line all used signals should be connected directly to the 
appropriate pins on ASIC4/5. 


ASIC4/5 SDAT 
MCLK Serial clock ASIC4/5 SCLK 


| 6 | SCK/EXON | Not used in this scenario | Donot Connect____| 


Signal Definition 


MSD and MCLK form a single master SIBO serial protocol channel. This is normally channel 7 on a 
Series 3 and channel 5 on an S3a. The serial channel clock can be continuously enabled to provide a 
free running clock for expansion devices. The frequency is fixed at 1.536MHz regardless of the 
system clock frequency. SDKs/INT and SCK/EXON are both dual function pins. SDKS and SCK 
form a single slave SIBO serial protocol channel. This can be combined with MSD and MCLK to 
form a bi-directional high speed data link. SDS/INT can also be used to as an active high interrupt 
input. The function of SDS/INT can be programmed in ASIC2 or ASIC9. A rising edge on the 
SCK/EXON input will bring the system out of the standby state into the operating state. VCC is a +5 
volt supply that is switched off when the system is in the standby state and is switched on when the 
system is in the operating or idle state. The maximum current that can be drawn is 25mA. Opening 
the pack doors on either an S3a or a Workabout will cut power to external peripherals. 


Physical Connector 


The reduced expansion port is made up of a 6-way two row connector spaced on a 2x3 way 0.1 inch 
pitch. The diagram below shows the physical connector numbering: 


Revision 1.00 Page 12 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Looking into Series 3 / 3a 


The male plug is connected to a 0.5m long plastic moulded 3-link cable assembly (part no. 25020013) 
which is terminated in a six-pin in-line connector which connects to a 6-way 1.5mm pitch transition 
header (part no. 47000106). 


The Psion Workabout 


The Workabout Expansion Interfaces 


The Psion Workabout provides a rugged and easy-to-use computer system for a wide range of mobile 
corporate needs. The machine can be readily adapted to support various peripheral units such as 
barcode scanners and modems attached to the expansion ports. The Workabout has a 26-way 
extended internal expansion interface and a special 11-pin reduced external expansion interface. 


Workabout Extended Internal Expansion Interface 


The pin-out of the Workabout 26-way internal Torson connector is outlined below: 


Torson 26 way connector pin Workabout Signal name 
NICD (not used) 


THM (not used) 
VIN (not used) 


Revision 1.00 Page 13 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


e = Vccl is 3.0V nominal power supply. Current available from Workabout is limited to 100mA. 

e =Vcc2 is 5V nominal power supply. Current available from Workabout is limited to 200mA. 

e RUN is low when powered down and high when powered up. It is used to power down or reset 
the peripheral module. 

e SCK2 and SCK3 are serial data clocks. The clocks are left running continuously at 1.536MHz 
when the serial port is in use. They are used to clock the UART in ASICS in the RS232 AT/TTL 
and AT/Barcode modules respectively. 

e SD2 and SD3 are bi-directional serial data lines used in the RS232 AT/TTL and AT/Barcode 

modules respectively. 

EINT1 and EINT2 are active low signals for interrupt input. 

EXON is an active high signal used to turn on the Workabout. 

All of the above logic signals are at 3.0V or 3.3V levels, depending upon the logic supply Vcc1. 

Lines currently described as unused relate to a yet unspecified codec interface. 


Workabout Reduced External Expansion Interface 


For the Workabout reduced external expansion interface, a new | 1-pin Low Insertion Force (LIF) 
connector has been designed for connecting the computer to the Cradle System. The computer 
mounted male LIF may be weather proofed, the cable mounted female LIF cannot. Currently the LIF 
connector cover can be moulded with a polarising pin in one of two positions. The facility exists to 
manufacture the cover with the polarising pin in two more positions, giving four possible variants. If 
more than four versions are required it is possible to have the cover and the socket bezel moulded in a 
range of colours to differentiate between variants. The polarising options are presented below: 


Pin numbers 
1st (1 GROUND 9 
2nd (________] SIGNALS 2,3,4,5,8,10 
1,6,7,11 


The step arrangement of the LIF Connector pins 


Cable mounted LIF (Female plug) Computer mounted LIF (Male socket) 


Revision 1.00 Page 14 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


3S 310 


@e0000 08 
ODOOOO 


Cable mounted LIF (Female plug) Computer mounted LIF (Male socket) 


Type A and Type B polarisation of the LIF Connector 


Revision 1.00 Page 15 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Pin Definition for LIF - PFS Connector 
LIF Connector Polarisation Type B 


Pin Pin Name Wire Colour Contact Direction Standard Function Cradle usage 
No Gauge (Cradle's 
perspective) 

1 LCA 710.1 Brown third Input Local’ Computer Active. High when the Used as an enable for the cradle 
computer is on. (The Workabout can source resident Xmod 5V supply. 
100mA from this pin and the HC/HCDOS 
5mA to power remote circuitry) 


EXON 710.1 Blue second Output EXternal switch ON, active high (+5V). May be asserted by a cradle resident 
Asserted by a remote” device to switch on Xmod. 
the computer. 
Xmod. 


se He 1 a eee eet Battery thermistor terminal. Allows remote“ function 
eae of the battery temperature. 


meal 1 Bead ie Output Disconnect Local” ASIC, active high (+5V). Asserted by the Cradle ASIC, 
(does not apply to Workabout). When this connects the cradle resident Xmod to 
signal is asserted the serial channel is the serial channel. 
disconnected from the local? ASIC4/5 in the 
HC resident Xmod (if present) and instead 
connected to a remote ASIC4/5 (if present). 


FN Te 
| 7 | vin | 28SwG Power supply to computer (+10V) 
| 8 | SCLK 710.1 | SerialchannelCLocK. 


GND 28 SWG White “fiat Power, [Seval channel Chev —_____ ground and -ve battery Standard function 
terminal (1 amp) 


SDATA 710.1 Serial channel DATA. 


11 STATUS 710.1 Pink third Cai STATUS. Connected to a pull-up resistor to Driven low by an open collector driver 
allow connection to an open-collector/drain when LCA is high and the cradle is 
driver. Normal usage is: low indicates the powered-up to allow the computer to 
presence of a remote” device. sense whether or not the cradle is 

connected. 


LIF Connector Polarisation Type A 


Pin Wire Colour Contact Direction Function 
No eine Gauge (Computer's 
perspective) 
ee oe RS2I2 signal 
a a RS232 signal 


77 Output | RS232 signal 
THERM [7101 [Yellow [ second_[ =] Battery thermistor terminal 


[svar [2sswo [Red [tind [- | tvebattery terminal ——SSSSSCSCSCSCSCSCSCSCC~C~* 
[3 [pe 701 [Grey [second [Input [ RS232signal OSS 
[9 [exp eswo [white [fist [= | Power, signal ground and ve battery terminal —____——SS—~S 


Definitions 

Computer HC, HCDOS or Workabout 

Cradle resident Xmod Expansion module fitted to the cradle, may or may not be present. 

HC resident Xmod Expansion module fitted to the HC, which contains the cradle interface and possibly another peripheral. 
HC peripheral A peripheral, located in the HC resident Xmod which is connected to the same serial channel as the cradle. 
Cradle ASIC An ASICS located on the main cradle PCB which remains connected to the serial channel 


irrespective of the state of DLA. 


1. | The term "local computer" implies the computer local to the LIF connector, i.e. the HC, HCDOS or Workabout, as opposed to 
a "remote" computer which might be connected via a cradle resident Xmod for example. 

2. The term "remote" implies something on the other side of the LIF connector to the computer. 

3. | The term "local" implies something on the computer side of the LIF connector including devices on an HC resident Xmod. 


Revision 1.00 Page 16 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Exploded view of the Psion Workabout 


Below is an exploded view of a complete Psion Workabout showing part numbers for various 
components and illustrating the positioning of the expansion interfaces. 


4 
g y 
o  # ” 
4 a § 8 
Ss 8 
4 gy Fa i 
f a Of i 
a 8 a a 
a « 
a 2 
8G 
Roo 
ae 
38 
a3 
3 
a @ ¢ 
me oON Sgt 
3 
ROS 
a 3 g 
® S +8 
Be $3 
$s $8 
a 8 28 
= 
o 
j z 
a 3 
a3 F | 
8 
a 4 9 Boa ey 
3 a a 9 3 
a g 4g 1 o 
& & a9 3 4 2 
# 8 . p 3 3 
zh ae 6 ¢ a 
3 i 3 f é i 3 " 
3 a8 a 8 2 3 § 
goa 
3 BS 
g a 8 Poa 
3 
5 : 
a 8 a 9 
a oF a + 
& § 
ff 42 
Oo oN bos 
ng 
a 3 
al 
a 
«38 
i 
hoon 
2 8 > 
f 9° a 38 
ag eg 
2 as 
& 
a 
$3 
Gc @ 
aa 
4 
a og 
3 
4 
o § 
8 
g 8 
& 
g 3 
a 
a S$ 
0 y 
8 3 
4 
8 
d 
1 a 
3 ages 
a Be, gy ee! 
8 g 3 
ae 
a 
3 
8 & 
4 
9 2 3 
p t ° ib 
a oO © 
3 Re eS 
3 y § 3 
4 3 
3 
ae oe: 
n oc = «© 
x 
» 
zg a3 
xg 
é 
a3 28 
4 a 3 6 
4 4 
s 3 ¢ 2 3 os 3 
a a 8 § 
a 4 hoa gs 4 $ 
3 ROS * 
§ a & aoa 
g 
g 8 i 3 
a 3 5 3 
3 i rf 
g 
Son 
8 38 
4 og 
F 2 9 
* 3 
8 
a a 4 
j 4:8 
8 ‘ 
a5 
3 
a 


Revision 1.00 Page 17 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The Psion HC range 


HC Extended Internal Expansion Port 


The Psion HC range of computers are intended to provide a rugged and powerful mobile computer 
system for a wide variety of demanding application requirements. As part of its adaptability, every 
element of the hardware is configurable from the plug-in SSDs to the expansion ports for peripheral 
devices such as bar code scanners, modems and magnetic card readers. There are two independent 
extended internal expansion ports at either end of an HC unit. The top port is termed the "A" port 
and the bottom one the "B" port. Each expansion port provides direct I/O with the processor, a SIBO 
serial channel, and connection to the power supply. It allows for higher powered expansion devices to 
be added by including a direct connection to the main 7.2 volt battery. 


Physical Connector 


The expansion port is made up of a 25 way single row connector spaced on a 0.1 inch pitch. The 26th 
position is a polarising key and should be left blank. The correct mating connector on the expansion 
device is made up from a number of Molex C-Grid series 90148 connectors. Pins | and 2 are ground 
and should have there own connector placed nearer the board edge to ensure the ground connection is 
made first when the expansion device is inserted. The required connectors are Molex 90148-1102 for 
the GND contacts and Molex 90148-1123 for the signal contacts. The diagram below shows the 
physical position of the connectors. 


=$f ene 98148-1182 3 

Se : EXPANSION D 
=e 

sad Abe COMPONENT SID 


fet 

feu) 
HHDE 
eorn 
AEM 
on 


38148-1125 


raftats afte 
+ [o}:o loo) en] 
Heonwnm 
Zuaorom 
Scteorn 
aa ne 


raftofea 
Lsfosfra 
wn 
Ox 
ol 
Fr! 


wi 
Zo 
OR 


ge 


voce 
(SPACE? 


SIBO COMPUTER 


Revision 1.00 Page 18 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Signal definition 


The following table defines the 25 way expansion connector:- 


Pin No. Name _ Sig. type Comments 

GND Power Should mate first when device inserted 

GND Power Should mate first when device inserted 

ADO  BCMOS 8 bit multiplexed address and data bus pulled low with 100 K resistors 
ADI BCMOS 

AD2  BCMOS 

AD3  BCMOS 

AD4 BCMOS 

ADS  BCMOS 

AD6 BCMOS 

AD7 BCMOS 

ALE OCMOS Address latch enable - high when valid address on ADO-AD7 

IOWR OCMOS I/O write strobe - active high, data valid on falling edge of IOWR 
IORD OCMOS I/O read strobe - high when device can place valid data on ADO-AD7 
EES OCMOS External Expansion Select - high during I/O cycles to expansion device 
SCLX TCMOS 512 KHz SCL signal for SLD bus - usually Hi-Z and pulled low 

DNC N/A For future expansion - do not use. 

THERM Resistor Connected to thermistor (bottom slot only - top slot DNC) 

VBI Battery Connected to the internal NiCd battery (bottom slot only - top slot DNC) 
Vsup Power Unregulated battery voltage - present all the time 

INTR ICMOS Active high interrupt input 

_EXON ICMOS Active low input pulled up to Vccl - pull low to switch machine on 

SD B CMOS SIBO serial protocol data line - pulled low 

SCLK TCMOS SIBO serial protocol clock line - Hi-Z in standby needs a pull down 
GND Power 

Vcc2 Power +5 volt supply, switched off in standby. Max current available = 50 mA 


AADNKRWN KH 


DNC (Do Not Connect) indicates that the pin should not be connected. The signal types are:- 


O CMOS CMOS output to the expansion device. 

B CMOS CMOS bi-directional line to the expansion device. 
T CMOS CMOS tri-state output to the expansion device. 

I CMOS CMOS input from the expansion device. 


All the CMOS signals including the ADO-AD7 bus are buffered from the main system busses and so 
present a load of one HC series logic gate. 


Direct I/O 


Expansion devices can be connected to direct processor I/O space using the following signals; ADO- 
AD7, ALE, IOWR, IORD, EES and INTR. 


ADO-AD7 is the least significant half of the multiplexed address and data bus, this means that up to 
128 I/O addresses are available for each expansion device. As only the least significant half of the 
bus is available and no bus conversion is done only even addresses can be used. 


ALE must be used to latch the address from ADO-AD7 for devices that require a stable address. The 
address is valid on the falling edge of ALE. Note that AO will always be low for valid writes to the 
expansion device and as such should not be used as an address line, Al should be used as the lowest 
order address line. AO can be used as an additional enable signal to stop odd I/O accesses disturbing 
the expansion device. 


EES is the External Expansion Select and is high during all I/O accesses to the expansion device, i.e. 


for I/O reads and writes to address range 100 to 1FF hex. for expansion port 1, and 200 to 2FF for 
expansion port 2. 


Revision 1.00 Page 19 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


IOWR is an active high signal which is high during all I/O write bus cycles. The data on ADO-AD7 
is guaranteed to be stable before the rising edge of IOWR and after the falling edge of IOWR. IORD 
is an active high signal which is high during all I/O read bus cycles. The ADO-AD7 bus is 
guaranteed to be tri-state before the rising edge of IORD and after the falling edge of IORD. The 
expansion device must present valid data on the bus when IORD is high, see the timing details below. 


INTR is an active high interrupt input to ASIC1. T his can be used as a directly readable bit or as a 
dedicated interrupt input. It must not be driven high when the system is in the standby state as this 
input is pulled down and will cause excessive standby current consumption. The diagram below 
shows the timing of the I/O write and read cycles. 


T/0 WRITE CYCLE 


ADS-ADT VALID ADDR 


VALID WwW 


QOD 


FES q_Tadstp _ plyTadhidy, 


| Tudstp | Tudhld | 


IYO READ CYCLE 


ADS-ADT VALID ADDR> 


} Tadetp fel adhd ,, 


| Thztd Trdste Trdhid 


Parameter 

Address set up time 
Address hold time 
Write data set up time 
Write cycle pulse width 


Write data hold time 

Time from Hi-Z to data active 
Read cycle pulse width 

Read data set up time 

Read data hold time 


Note the typical values given are for an HC with a system oscillator of 7.68 MHz. 


The SIBO serial channel 


A single SIBO serial protocol channel is provided on each expansion port. Expansion port | is 
connected to serial channel 5, expansion port 2 is connected to serial channel 6. The serial channel 
clock can be continuously enabled to provide a free running clock for expansion devices. The 
frequency is fixed at 1.536 MHz regardless of the system clock frequency. This frequency is a 
multiple of the SLD clock rate and of all normal RS232 baud rates. 


High Speed Side Port 


Port C on an HC houses an 8-pin in-line connector that allows access to a high speed SIBO serial 
interface. This interface is currently used only by the HC cradle peripheral. Its pin-out is outlined in 
the table overleaf: 


Revision 1.00 Page 20 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


[Pin | Signal | Type | Description, 


fo | Sb7_ | InOut__| Bi-directional Serial Data line- Side portC 
[8 TSEN Input Battery temperature sensor 


Power supplies 


Two power supplies are available for expansion devices these are Vcc2 and Vsup. Vcc2 is a +5 volt 
supply that is derived from Vsup. Vcc2 is switched off when the system is in the standby state and is 
switched on when the operating or idle state is entered. Each expansion device can draw up to 50 mA 
from Vcc2. If an expansion device requires more than 50 mA or cannot be powered down when the 
system is in the standby state the Vsup power supply must be used. Vsup is the unregulated supply 
directly from the main system batteries or from the DC jack input. It will be in the range 5.5 to 12 
volts under normal conditions. To use Vsup the expansion device must regulate Vsup to 5 volts with 
a low drop-out linear regulator. Care must be taken to not be active and driving any signals high 
when the system is in the standby state as Vsup is always present. This can be achieved either in 
software or by using Vcc2 as a signal indicating the active state. 


Mechanical Information 


Mechanical details regarding the numerous build variants and accessories that currently exist for the 
HC are presented overleaf. The peripheral expansion boards for these build variants are housed in a 
special plastic casing that can be machined to hold the requisite connectors. In the matrix, ae 
indicates that the relevant combination of HC and accessory are compatible and an X indicates that 
the combination is not compatible. Following the build variant table are two diagrams that display 
exploded views of the HC expansion connector and the HC Expansion Board complete with part 
numbers and dimensions. 


Revision 1.00 Page 21 of 115 pages 


The Psion SIBO Hardware Development Kit 


Build Variants 


With EL Backlighting 
Without EL Backlighting 


Industrial 


Non-Industrial 


Keypad Variants 


53 Key A/N UK 2401-0026 
A/N European 2401-0051 
A/N Scandinavian 2401-0050 
Numeric only UK 2401-0046 
DOS Keypad 2401-0147 
53 Key A/N USA 2400-0026 
HC Expansion Modules 


RS232 / Parallel (Printer) 1502-0001 
25 way D type (F) + 9 way Mini DIN 
Certified FCC Class B / Passed VDE Class B 


RS232 / TTL 

1502-0039 (IP64), 1502-0040 (NON IP64) 

9 way D type (F) + 9 way D type (M) 

Passed FCC Class B / Passed EN55022 Class B 


UK Modem (Asic 8) 1502-0010 
RJ 11 connector 
BABT Approved in UK, BS6301 (Safety) 


Barcode Only 

HP Wand HBCS-A207 + Plug + EXMOD 1502-0020 
Wand Welch Allen + Plug + EXMOD 1502-0021 
FCC Class A/ Passed VDE Class B 


RS232 / Barcode 1502-0044 
9 way D type Quick Loc(F) + 9 way D type (M) 
Complies with FCC Class A 


MCR / Scanner / RS232 1502-0003 
Scanner NipDenso + Plug 1502-0022 
Scanner DigVision + Plug 1502-0023 
Magnetic Card Reader + Plug 1502-0024 
Certified FCC Class B / Passed VDE Class B 


LIF / RS232 (Under development) 
9 way D type (M) + 9 way LIF- PFS (M) 


LIF / TTL (Under development) 
9 way D type (F) + 9 way LIF- PFS (M) 


LIF / BARCODE 1502-0043 
9 way D type Quick Loc(F) + 9 way LIF- PFS (M) 


Vehicle / TTL 
9 way D type (F) + 9 way LIF- RS232 (M) 


16550 RS232 / TTL (Under development) 
9 way D type (F) + 9 way D type (M) 
Complies with FCC Class A 


Printer (High Res.) 1502-0037 
Laser Scanner 1503-0012 


Fast Charger Variants 


Fast Charger with Holster (Due Jan 95) 
Fast Charger without Holster (Due Jan 95) 


Additional Accessories 
Nicad Battery Pack 500 mA 1503-0005 


Revision 1.00 


Psion PLC (c) May 1995 


CHARGER 


a a a Ee 
i ie IE a a 
ee ee 
Re ca Da ca 


ans he ae Ss eee 
FS a a a a 


Page 22 of 115 pages 


Psion PLC (c) May 1995 


The Psion SIBO Hardware Development Kit 


Corporate Hand Held (CHH) 


Expansion Module Exploded Assembly Drawing 


(yovig) Sso0-zoz9 


(USENNN LYVd YSLINO OSTY) (A3N9) £000-20z9 


YANVIG NOISNVdX4d 138V1 


(440 2) 2000-z0¢g 
WSO IZOd WWOXZZ% MINIS 


(OV1E) 9107-2018 


(AJN9) 9101-2018 
ONITINOW Y3LNO NOISNVdxX3 OLS HHO 


(wov1d) $10Z-Z018 
(AIUD) SLOL-ZOL8 
ONIGINOW YSNNI NOISNYdX3 HHO | 


6000-0072 
ANVIG dd 


SNOISNSNIG YSLLNS 
ANVIG NOISNVdX3 138V1 


Page 23 of 115 pages 


Revision 1.00 


Psion PLC (c) May 1995 


t 


The Psion SIBO Hardware Development 


QrOr o22 ILD :xW4 
008! 802 120 “7131 
1G) HIM 


NOONOT N/OIl 


AS 18NOQYVH 61-21 
Jd NOd 


MSV LENOd Ni dl 
JNWOS ION OG 


(SOs 2) ONDOEL =O 
w300 34 OL G3U0Y vey 


26, 


94 01 GMQy SFI NOILWOOT 


26/1/91 


Sa @ SINSNOGNOD 40 
wa) 38 OL G200V vw 


26/0178 


‘Gadd NOWOWISIS 
AHOIBH LN3NOEWOD W207 


06 /c0/zal 


108 X3T0K 
a300¥ $89 8ou93~N09 


oss 9792 


SSI Sas 


SONVHO, 


SmAOVd NOISNVdx4 


SH T1¥ A044 GssyINGS 


NOILYWAOSANI 4H 


L SMOHS SONIMVAC Sit 


LH513H LN3SNOdWOD 
X¥W ONIMOHS 311 408d 


216 


cay) Y_NOISN3WIC 


C30N31LX3 


CAVONVLS 


JdWwOS aNv 


qa.0N3d vaav 


A11V901 NO3IaLS34 


COMPONENT HEIGHT RESTRICTION 


(SEE PLAN VIEW) 


(SOd 2) ONIMDVYL ANY 
WOS4 3384 38 O1 voav 


CAVA 92 WiOL) SYOLO3NNO9 


LTO 


SOd 2) SIN3NOdWOD ANY 
WOSs 3384 34 OL vaav 


: @szaze @ S3143S 8y106 X370N 


a2 


4.5 BOTH SIDES 


1 
| 
31.75 CRS l 31.75 CRS 


Page 24 of 115 pages 


Revision 1.00 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


6. ASIC 4 


What is ASIC 4? 


ASIC4 is custom integrated circuit designed for use in Memory Packs (called SSDs) and peripheral 
devices. Its primary purpose is to convert the PSION Serial protocol into the signals required to 
address memory and memory-mapped peripherals. A typical Series 3/3a ASIC4 peripheral will 
consist of an ASIC4 connected to port C of the host machine and a peripheral chip/device mapped 
into ASIC4's addressing space. An example could be an ASIC4 connected to a simple 1k memory 
device: 


Chip select 


To write a value, <v>, to address <addr>, the appropriate control codes must be sent along the port 
C Psion Serial link to assert <addr> on ASIC4's address outputs and <v> on ASIC4's data outputs. 


ASIC4 Addressing and Modes 


ASIC4 has an 8 bit data bus and a 28 bit address bus. Also provided are eight chip select lines that 
form selectable addressing blocks each of a size defined by software. The default is 32Kbyte/block. 
The filing system will set this to the appropriate size while accessing memory in the upper portion of 
the address space. 


ASIC4 has two basic modes of operation, namely ASIC5 Compatibility (or SSD) mode and ASIC4 
Extended mode. To select the mode, ASIC4 must be selected with an appropriate ID. This is 
achieved by writing a SIBO serial protocol slave control frame, as detailed in chapter four, to the 
ASIC prior to sending any read or write requests. After sending this frame, the so-called Info Byte is 
read off the data bus. Details concerning the meaning of the various Info Byte bits are provided in the 
following section. In the case of SSD mode, the ID is 2 and for ASIC4 Extended mode, the ID is 6. 


Putting ASIC4 into SSD mode makes the chip compatible with all current versions of existing SSD 
software in production by Psion including all HC, series 3/3a and MC software. In this mode, ASIC4 
mimics an ASICS in pack mode (see next chapter). This is because ASIC4 was originally designed to 
be a cut-down version of ASICS and so from the outset it was necessary to make previously existing 
ASICS software run on the new chip. The maximum address space in SSD mode is 21 address bits 
and 4 chip selects (which comes to 4 x 2Mb). In ASIC4 Extended mode, ASIC4 is capable of 
addressing up to 28 address bits (256Mb). In this mode, in addition to the Info Byte, a further 4 bits 
of information can be elicited from the state of the address lines A27-A24 during reset. Of these bits, 
the state of A27 (bit M) determines whether ASIC4 is going to be used as a standard SSD (M=0) or in 
a mixed mode (M=1) comprising of memory devices and peripherals. It is only the latter case which 
is of interest to the potential developer since this is the mode intended specifically for peripheral type 
expansion. In mixed mode ASIC4's address space is split into two equal halves. The lower half of 
the addressing range is set aside for memory-mapped peripherals and can be used for any purpose. 
The upper portion of the address space is reserved for pure memory. The Series 3/3a, Workabout and 


Revision 1.00 Page 25 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


HC filing system is able to use this memory (which does not have to be present) as an additional 
storage medium. Typically it will be a ROM containing the software that controls the peripheral. On 
reset, configuration data is supplied to ASIC4 on its data bus lines which the filing system can read 
in order to determine what form of and how much memory it has available in this upper region. 


In mixed mode chip selects are split into four selectable peripheral blocks and four selectable memory 
blocks. CSO-CS3 are for peripheral access. CS4-CS7 select memory devices one to four. This set-up 
is illustrated below: 


Peripherals 
S1 
$2 
$3 
Total 
Addressing S4 
Range Memory 
(256Mb) SS 
S6 
S7 


Reset and configuration 


As indicated earlier, in mixed mode, following a reset or power up ASIC4 will read the form in which 
to configure itself from the data on data lines DO-D7 (the Info Byte) and address lines A24, A25, A26, 
A27 (most significant nibble of the Extended Info Byte). The table below shows the meaning of each 
of these lines during reset. 


| A27 | A26 | A25 | A24 | D7 | Do | Ds | D4 | D3 | D2 | Di | DO | 


Don't care, some 000 RAM 00 1 device No memory 
codes are reserved. | 001 Typel Flash | 01 2 32Kbyte 
000 No peripheral | 010 Type2 Flash | 10 3 64Kbyte 


001 T3Link 110 ROM 114 128Kbyte 
010 3Fax 256Kbyte 
Contact Psion for 512Kbyte 
an official code. 1Mbyte 


Pull up, pull down resisters would usually be used to place these lines in the desired state on reset. 
High value resisters of typically 100k would be used to allow ASIC4 and bus devices to drive these 
lines to other levels during normal operation. 


ASIC4 should be powered from its host Series 3/3a/HC. High current peripheral chips or volatile 
memories should have their own supply. Whenever the Series 3/3a/HC is powered down, has its 
batteries removed, or has it's pack doors open, any attached ASIC4 will be powered down and reset 
upon resumption of power. Taking the 3Fax as an example with one Read Only Memory device of 
512k the required configuration is: 


Revision 1.00 Page 26 of 115 pages 


The Psion SIBO Hardware Development Kit 


ASIC4 Pin-out 


Pin No Pin Name 
50 DO 
49 D1 
48 D2 
47 D3 
46 D4 
45 D5 
44 D6 
43 D7 

13 AO 
12 Al 

11 A2 

8 A3 

7 A4 

6 AS 

5 A6 

4 AT 

3 A8 

2 AQ 

1 Al0 
64 All 
63 Al2 
62 Al3 
61 Al4 
60 Al5 
29 Al6 
28 Al7 
27 Al8 
25 Al9 
24 A20 
23 A21 
22 A22 
21 A23 
20 A24 
19 A25 
18 A26 
17 A27 
37 CSO 
36 CS1 
35 CS2 
34 CS3 
33 CS4 
32 CS5 
31 CS6 
30 CS7 
16 OE 
14 WR 
15 VPS 
39 POR 
40 SCLK 
38 SDAT 
59 SDIR 
51 LBO 
56 MCSD 
52 INO 
53 INI 
54 IN2 
55 X2D2 
57 ATST 
10 VDD 
42 VDD 
9 GND 
26 GND 
41 GND 
58 GND 


Revision 1.00 


Direction 
VO 
vO 


fe) 


~*=“O0O000000000 


fo) 


PWR 
PWR 
PWR 
PWR 
PWR 
PWR 


Pin Description 

Databus 

Databus 

Databus 

Databus 

Databus 

Databus 

Databus 

Databus 

Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register ATO 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT 1 
Address bus - register AT2 
Address bus - register AT2 
Address bus - register AT2 
Address bus - register AT2 
Address bus - register AT2 
Address bus - register AT2 
Address bus - register AT2 


Address bus - register AT2/Oscillator Output in PSPRAM Mode 


Address bus - register AT3 Inputs to set device size on reset 
Address bus - register AT3 Inputs to set device size on reset 
Address bus - register AT3 Inputs to set device size on reset 
Address bus - register AT3 Inputs to set device size on reset 
Device chip selects 

Device chip selects 

Device chip selects 

Device chip selects 

Device chip selects 

Device chip selects 

Device chip selects 

Device chip selects 

Output Enable/Refresh in PSRAM Mode 

Write pulse 

VPP control 

Reset input 

Serial clock input 

Serial Data input 

Protocol Direction indication Bit 

Low Battery detect driver output (Open drain) 

PSRAM Mode Select 

General Purpose inputs 

General Purpose inputs 

General Purpose inputs/Refresh Disable in PSRAM Mode 
Oscillator Input for PSRAM Mode 

Test input (pull high to put device into address test mode) 
Power inputs 

Power inputs 

Ground 

Ground 

Ground 

Ground 


Psion PLC (c) May 1995 


Page 27 of 115 pages 


The Psion SIBO Hardware Development Kit 


A11 A12 A13 A14 A15 SDIR GND ATST PS OSCIN IN2. IN1 INO LBO DO D1 


- LU Li Lt Ly ae L Ls LI Li 


62 61 60 57 56 54 53 52 51 


64 


A10 48 D2 
AQ 47 D3 
A8 46 D4 
A7 45 D5 
A6 44 D6 
AS 43 D7 
A4 42 VDD 
AS ASIC4 41} —J GNo 

GND 40 SCLK 
VDD 39 POR 
A2 38 SDAT 
Al 37 cso 
AO 36 cs1 
WR 35 cs2 
VPS 34 CS3 
OE 33 cs4 


17° 18 «#19 20 21 22 23 24 25 26 27 28 29 30 31° 32 


Rigizipininigiolgipinipimdeig 


A27 A26 A25 A24 A23 A22 A21 A20 A19 GND A18 A17 A16 CS7 CS6 CS5 
OSCOUT 


Diagram of ASIC4 Pin-out (NEC) 


Revision 1.00 


Psion PLC (c) May 1995 


Page 28 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


7. ASIC 5 


What is ASIC 5? 


ASICS is custom integrated circuit designed for use in Memory Packs (called SSDs) and peripheral 
devices. ASICS provides three primary functions. A built in UART provides for serial 
communication at baud rates of up to 48000 baud. General purpose I/O pins provide for a wide range 
of control and communication applications. Finally ASIC5 provides address and data lines for access 
to memory devices and memory mapped peripherals. A typical ASICS peripheral such as the 3Link 
consists of an ASICS connected to port C of a series 3/3a, a ROM memory device mapped into 
ASICS's addressing space and line drivers to convert the UART signals from ASICS into standard 
RS232 levels. 


Chip select 


ASIC5 rea Memory 


RS232 Line Drivers 


Psion Serial link 


ASIC5 Modes 


ASICS can operate in two modes. In pack mode ASICS generates all the address, data, and control 
signals necessary to access memory devices. No peripheral functions are available in this mode. In 
peripheral mode ASICS has only limited memory address capabilities as some or all address and 
control lines are reused for I/O purposes. ASICS is placed into peripheral mode by setting the 
peripheral bit in ASIC5's PBMODE register. 


ASIC5 as a UART 


ASICS contains a full function UART which supports baud rates of up to 48000 bits per second. In 
order to use ASIC5 as a UART, ASICS5 must be placed into peripheral mode. In this mode the input 
signals PAO, PAI, PA2, PA3 become the UART inputs RX, CTS, DSR, and DCD respectively. The 
output signals PDO, PD1, PD2 become the UART signals TX, RTS, and DTR. Serial data is 
transmitted from the TX line. Incoming serial data is received by the RX line. RTS and DTR can be 
used for handshaking or as general purpose outputs and need to be set high or low explicitly by 
software. CTS, DSR, and DCD can be used for handshaking or as general purpose inputs. 


The Psion SIBO serial link which connects ASIC5 to a host computer is a two wire interface 
consisting of a data and a clock line. ASICS generates it's baud rate clocks from this clock line. 
Under normal operation, clock pulses along a Psion SIBO serial link only accompany data frames. To 
be able to generate baud rate clocks ASICS requires a steady clock from the Hosts Psion port. To 
facilitate this, Psion serial links can be put into a mode called continuous clocking where clock pulses 
are generated regardless of whether there is any actual data to be transferred. Continuous clocking 


Revision 1.00 Page 29 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


increases power consumption and Psion serial links should not be left in this mode unnecessarily. 
The UART portion of ASICS is capable of generating interrupts when characters are received, when 
the transmitter is awaiting a character to send and when there is a change of state on the handshaking 
lines. ASICS has only one, active high, interrupt line. This line is shared between these interrupt 
sources. When an interrupt is generated it is the responsibility of software to determine the cause of 
the interrupt. 


A character to be transmitted should be written to the Transmitter Holding Register where ASICS will 
convert it to serial form for transmission. The register will be emptied once the character has been 
transmitted. ASIC5 contains no internal buffering. The Transmitter Holding Register must be empty 
before writing a character to it. The state of the Transmitter Holding Register is reflected in the 
Transmitter Empty bit in the UART status register. Enabling the Transmitting Holding Register 
interrupt will cause ASICS to generate an interrupt every time that the Transmitting Holding Register 
becomes empty. Reading the UART Status Register will clear the interrupt. Received characters are 
copied into the Receive Character Register. If the Receive Character Interrupt is enabled, ASICS 
generates an interrupt on each character received. If the character is received in error due either 
parity, framing or overrun errors, appropriate bits in the UART Status Register are set to reflect this. 


ASIC5 for parallel I/O 


Lines PAO-PA7 form a general purpose, non latched, 8 bit input/output port. All access to this port 
take a total of twelve clock cycles. The clock is generated from the Psion Serial Link. Actual 
memory access cycles only last for one clock cycle. Twelve cycles are required because data being 
sent or received needs to be converted to or from the Psion serial format. Because of the conversion 
read accesses occur on the third cycle, write cycles on the twelfth. This is usually of no real 
consequence to the peripheral designer 


In peripheral mode CSO will be taken low for one clock period each time Port A is accessed. Data 
outputted from this port will remain valid for only the period that CSO is low. In pack mode Port A 
forms the data bus in memory mapped systems. A read from or write to Port A in this mode will 
result in one of the lines CSO-CS3, being taken low for one clock period. The line which will be 
taken low will depend on the address being generated for the access. During read cycles OE line will 
be taken low and remain so for 10 cycles. Data present on PAO-PA7 must remain stable for the last 
nine cycles. During write cycles the WR_B line will be taken low for the second half of the cycle over 
which one of CSO-CS3 is low. If port B is set to counter mode, accessing port A will result in the 
counter being incremented upon completion of the access. 


ASICS can be programmed to generate an interrupt whenever the state of line PA4 changes. Reading 
port A will clear this interrupt. One use of PA4 is as the BUSY line in a Centronics port 
implementation. 


The Lines PBO-PB7 can be programmed to operate in four different modes. Two of these modes are 
for testing purposes and will not be discussed further. In latched mode, data written to the Port B 
resister is latched onto the Lines PBO-PB7 and will remain there until a following write to Port B or a 
reset condition occurs. In counter mode, the binary value on lines PBO-PB7 is incremented following 
any access to port A. With ASICS in pack mode lines PBO-PB7 form the address lines AO-A7. 
Placing port B into counter mode allows 256 consecutive memory locations to be read without need to 
set-up the address of each access. 


Lines PDO-PD7 are general purpose outputs. In pack mode these form the address lines A8-A15. In 
peripheral mode lines PDO, PD1, PD2 become UART outputs. 


Lines PCO-PC4 in pack mode form the address lines A16-A20. In peripheral mode lines PC4 and 
PC7 become inverted inputs and can be used as edge triggered interrupt lines. PC5 becomes the 
interrupt output line. PC6 becomes a general purpose latched output. PCO-PC3 become a dual 
synchronous serial port for use in magnetic card systems. 


Revision 1.00 Page 30 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


ASIC5 for Barcodes 


Psion barcode peripherals use the UART functionality of ASICS to receive data from a dedicated 
barcode scanner IC. 


ASIC5 for Card readers 


Magnetic card readers generate clocked serial data. ASIC5 contains two synchronous serial ports for 
connection to card readers or other peripherals which generate clocked serial data. 


Reset and configuration 


Following a reset or power up ASIC5 will read the form in which to configure itself from the data on 
data lines PAO-PA7. Line PC6 is used to select whether ASICS is to operate in pack or peripheral 
mode. The table below shows the meaning of each of these lines during reset. In peripheral mode 
lines PAO-PA7 should be set to give an indication of the type peripheral the ASICS is forming. 
combinations of types can be used. 


000 RAM 00 1 device No memory 

001 Typel Flash | 01 2 32Kbyte 

010 Type2 Flash | 10 3 64Kbyte 

110 ROM 114 128Kbyte 

1 1 1 Write protect 256Kbyte 
512Kbyte 
1Mbyte 


Peripheral Mode Type 


RS232 port 
Centronics (Parallel) port 


Hx KK KK XX 
xo KKM KK XX 


0 
0 
0 
0 
0 
0 
0 
0 


Pull up, pull down resisters would usually be used to place these lines in the desired state on reset. 
High value resisters of typically 100k would be used to allow ASICS and bus devices to drive these 
lines to other levels during normal operation. 


ASICS should be powered from its host Series 3/3a, Workabout or HC. High current peripheral chips 
or volatile memories should have their own supply. Whenever the Series 3/3a/HC is powered down, 
has its batteries removed or has its pack doors open, any attached ASICS will be powered down and 
will be reset upon resumption of power. 


Revision 1.00 Page 31 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


ASIC5 Pin-out 


A10 Ali A1l2 Ai3 NC A14 A15 DO D1 D2 


DONO o net 


ASIC5 


14 15 16 17 18 19 20 21 


MAMAMAAMMo 


WR VPS OE A20 A19 NC A18 A17 A116 CS3 CS2 


ASIC 5 current pin-out (TI version CF30179) 


Revision 1.00 Page 32 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


8. EXAMPLE PERIPHERALS 


The ASIC4 Example Interface Board 


The ASIC4 Example Interface Board detailed in this chapter is intended to provide the developer with 
a simple example of a Psion ASIC4 peripheral. To this end, the actual practical usefulness of the 
hardware is of secondary importance. In fact, the board essentially consists of eight LEDs connected 
via some latches to an ASIC4. Using a device driver, the host machine is able to control the status of 
the LEDs. Specifically, the board translates SIBO serial protocol signals into a parallel 8-way data 
bus format that can be used to set the various 74HC series latches and gates. It is intended that the 
board can be readily adapted to run on all currently available Psion machines. The only physical 
change that need be made concerns connection to the host machine's external expansion interface. 


In the following circuit, an eight-bit tri-state data buffer, U3, and an eight-bit output data latch, US, 
are commoned together to the eight LEDs thereby enabling their status to be sensed and set. In 
addition, a facility for generating hardware interrupts is provided by means of a suitably connected 
switch, S1, and a third eight-way buffer, U4. U4 is the interrupt switch status buffer. It holds the 
values of the two input switches S2 and S3 which are read as part of the interrupt service routine. 
Depending on the value of the switch positions, a different response can be output to the LEDs from 
the set buffer, US. One of the D-type flip-flops in U6 is used to latch hardware interrupt signals into 
the INT line (pin 5) of the reduced external expansion interface connector. On completion of the 
interrupt routine code, it is necessary to reset this flip-flop and hence the interrupt hardware by means 
of a write to address Al. Address decoding is provided by two 2-to-4 decoders on chip U1 paralleled 
to address lines AO and Al. A circuit diagram of the ASIC4 Example Interface Board is presented 
overleaf for the case of a host S3a. 


Note that it is possible to construct this circuit with or without the compiled driver code in an on- 
board ROM. The developer merely has to set the resistors on the three data bus lines DO-D2 such that 
the corresponding info byte conveys the appropriate information. The meaning of the various bits in 
an ASIC4 info byte was discussed earlier in chapter 6. If a ROM is to be used, then the info byte read 
off DO-D7 on reset should include bits 001 on lines D2-D0. This requires the R1/R2 optional resistor 
to be connected to Vcc. If a ROM is not used, as was the case with the constructed test circuit, the 
data bus lines D2-D0 should be set to 000. This is done by choosing the resistors connected to ground 
from the three R1/R2, R3/R4 and R5/R6 pairs. 


Revision 1.00 Page 33 of 115 pages 


Psion PLC (c) May 1995 


The Psion SIBO Hardware Development Kit 


VOD 
voc voc voc voc 
3 
cs ca cio _|+ caa For 128K Bute ROM fit option resistors Ri, R4, RG, RE and Rio eibe 
idon toon ioon Our evs For no ROM fit option resistors RZ, R4, RE bo 2 
ue ve ve as VOD 
SNC GND GND GND 
1 
3 
Xf RE-/R4 
vor GND 
res Di 2g 100K 
ag voo | 338 
bo = ae base es Do 
Di 14 Bd 1 
AS Bi 
DE Be be (45 De 
veo DS ce be Cie mE v Biel 
Da 18 ba SNC 
oS aé ba Te DS 
az BS 
R22 [ery AS be 20 [T= 3 
100K Br aS BS [ei isk RE RE 
aio fa 100K 
ort ze | 22 bz z 
Al2 
ails oe [24 
7 ate 1 
aaa oe awe hae 
Aiz L 
ae GND 
eto nigga | ao 
vor voc 
ZEK—ine ROM DS R16 100K 
Ss Is 
RT-RE RS/RL0 
vos z z 
7 FaHcT4a 
ja oR oR 
R26 
Rea 100K 1 1 DF R20. 100K 
LooR 
GND 
GND 
Ree SND 
aoe t R27 ba 
voc LED GND 
CONNL 
sp7 bo * 0 
sck7 b-# = Bo 18/ivi = 1ai +329 
= Di is a_i LED ND 
sDSs/INT iv2 0 1Az 
SCKS/“EXON a Wie D2 14 is. 1AS & P2 
z z Ds iz = Ps 
Wor * a vo ava iaa 
4 z bas ii_F4 
She , a. be revi 281 Ge re LED GND 
YE 2Yz ZAz 
CON COMMS CONN be oer te be S| S02 282 (re Pe 
bre) S)5: Soy bere 
FPS4HC1sg 
GND te het LED GND 
vor 28 brs 
DL uza 
1 OE 4 ae FaHceas FaHCETS 
z 3 ORD LED ND 
2 cso 2 FaHca4d 
A t ua 
WF Baves clr Se T4Hese DO 18 Tyg LAL 
GND 1006F El tel ge: {ee LED GND 
1B a De 14 
ive 9 1az 
Mee Nf 14) 4 vo BS tetiva iad 
D2 GND U2B is ba 3 
B vi Zvi ZAL 
4 WR 4 oS + LED GND 
Y2 2vz BAZ 
= 6 Lor 15 bss 
Gc YS 2yYe 2As 
=P = Dre 3/oy4q Baa 
FaHCLss 
yo OBAYSS FaHese ee 470 LED GND 
GND Vos a Si voc ¥ v 
vos J" GND SND DATA OUTPUT 
vor FaHCe44 
DOS la Us6Al Lk Interrupt Sw 
a: 
= Ne Saal = a B Db 2 CC? 1993 (PSIOS PLS. 
aa ADDRESS R-M FUNC 3 Interrupt In 
+ Bava fal RYH Read & write to latch SLK Eiki Sp ee) omnes 
GND rs Md Clear Interrupt els; = R25 
1 R Read status 100K Poe REY : oO 
status Bit Func F4HCr4 Title 
a Ineut a 
L Tneut 1 > ASICS Example IF 
2-5 Not Used GND GND Size Pocument Number REV 
6 Interrupt Line B 7 lo.s 
? Interrupt Latch : 
Date: Aerial 19, 1995|[Sheet i_of Z 


Page 34 of 115 pages 


1.00 


1S10n 


Rev 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The Psion 3-Link 


The Psion 3-Link is an ASIC5-based peripheral that enables the user to transform SIBO serial 
protocol signals into RS232 format data so that a host Psion machine can communicate with a PC or 
printer. The diagram below shows the schematic of a TTL level RS232 based expansion device. The 
interface is based around ASICS and allows the standard RS232 device driver contained in EPOC to 
be used. 


Transistor Q1 provides a switched power rail for any other expansion device. This rail will 
automatically be switched off when the RS232 port is closed. D1 is required to isolate the supply so 
that the external device does not back power the SIBO computer when it enters the standby state. If 
the additional device does not require a supply or only uses a few microamps then Q1 and D1 can be 
omitted. Vcc and the supply for the expansion device can be directly connected to Vcc2. 


If CMOS level RS232 signals are required then IC1 can be replaced with a 74HC244 device. If 
inverted sense RS232 signals are required, IC1 can be replaced with a 74HC241 device. 


The diagram overleaf shows the circuitry for an ASICS-based 3-link with ROM. 


Revision 1.00 Page 35 of 115 pages 


Psion PLC (c) May 1995 


The Psion SIBO Hardware Development Kit 


vec 
Rig 
Icz vec 100K 
64/128K PROM SITE E 
B 
ag 12Tag wy po Laz ba 
ta ¥ 14 Di 
AL D1 
To é TS Be 
Az Dz 
g id Da 
as DS 
3 tg ba 
Aa ba 
id 15 DS 
aS DS 
20 DE 
AS De }s¢ = 
ay DF 
ae voc voc 
ag 
Alo vec 
AlL - 
A1lz ne |S? 
ars ver 4 i 
Ais Pst [22 +08 ce cz 
$3 rea Our /25v idon io0n 
Ale. + 
N 
B 
* 
T 
le t GND 
GND 
ND Fs 
ey eee 2g 
Re 100K TRL + 
BCH 1 cs cz 
+ 1ur/50¥ LuF/so¥ 
GND vee 
mS 1 | s 
aL 
rs 
82 (ita 1 ies 
veo 22 [aa i wees 
23 i 19° + iOurv2sy 
D1 Fi 14 + ¢ 13 
" 24s ex i ca 
| 1 4 aa c 
= vor 15 | coy yo LAZ ayes 
2 t 16 7 SKT1 CASE 
za 2- Fi 
Teu uF 7254 
BAYS? I FaHorS 7d TitN taout 2 GND SKTL 
36 e _DTR 
PBO  Y¥ PAD TBIN TZOUT RLSD/bco| 
ba PBL © pai }32 294 7 SIN TzouT 2 rs RX 
4 tad Sa ei ze _Tx 
x * PBZ paz [3 T4IN T40UT Tx 
2 PES paz = 3 Pare DIR 
PB4 paa [22 £4 R1OuIT R1IN p32 _RX__§_+ t GND 
a ee PBS pas fed eno se] RZOUT R2IN Pst—Bek . DSR 
PES Pas pse 25) REOUT RSIN bee—GeR 4 RTS 
PE? PA? R4ouT RaIN * cts 
DS, ig Te RI 
* a WEE — RS0UT . RSIN * RI 
PDO poco i at S| 
= a PDL pci H2 24 eR ql sp }25 SIBO RS2S2 CONNECTOR 
PDE pez He ibe Ria L c 
BAYSS co: pea fas REG Too 100K a mMaxzan GND 
12 ciolesilcizicizicis4 
PDS pes 
SMB PDS roe 3S 
PD? pe? L414 L GND in Jin Jin Jain Jain 
| 1008 R4 25 /ep zen b24 GND vovVoov¥ vo 
1O5R at 27 €39 Pox GND GND GND GND GND 
' CLK eSi 
26 2 
FOR cs2 
i7q Fo s T 
3g N53 PIL 
cs NG BD ¢np PL2 fh 
100pF iz 
veo asics [8 4 
GND 
GND ND R? 
RL 100R 
100K Sue 
o——___| 
cL SH SPDT 
vee 100n 
CONNI 
cer GND 
SRT ee RG RS 
SDS/INT BS Copuriaht CC) Psion PLO 1991 
ScKS/ExON PS 
Vee bs File name! CONHH DRAFT RS232.5CH 
yee Bg ioorR is a 10k Braun: MG 
CON COMMS CONN R20 B2xe4—Cay7 PCB Rey 1.4 
100K Title 
¥ 2|a 
GND Rev 1.2 Move SD (pin 25 IC2> from pin 23 to 21 of Ici : EONSUMER Bases ExCeL on 
Rev 1.3 Alter Ri? from 100K to 10K Size Pocument Number REV 
Rev 114 Added C1io—c14 = 
Rev 1.5 Moved C3 to CLK input GND GND is 6500.0008 cata 
Date: June i0, i953 Sheet i oF L 


Page 36 of 115 pages 


1.00 


1S10n 


Rev 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


9. DEVICE DRIVER OVERVIEW 


Introduction 


Once a piece of peripheral hardware has been designed the appropriate software must be written to 
control it. All hardware on Series 3/3a, Workabout and HC machines is controlled by logical and 
physical device drivers. These act as the logical low-level software interface between a piece of 
hardware and an application that uses it. The remainder of this document is concerned with the 
methods by which a device driver is able to communicate with and thereby control an ASIC4 or 
ASICS-based peripheral. 


APPLICA TION SOFTW ARE 


Psion C PLIB call interface 
LOGICAL DEVICE DRIVER 


PHYSICAL DEVICE DRIVER 


PHYSICAL HARDW ARE 


This chapter is intended to guide the programmer through the central issues involved in writing 
device drivers for peripherals that attach to the family of Psion host machines based around the 
proprietary SIxteen-Bit Organiser (SIBO) architecture. The purpose of a device driver is to abstract 
away the hardware details required to conduct communication between a peripheral and a software 
application that uses that peripheral. The device driver therefore performs the logical processing 
required to translate low level hardware instructions into high level application services. Psion device 
drivers are written in 8086 assembler and following convention are divided into a logical layer 
residing over a physical layer. A physical device driver (PDD) contains the code required for talking 
directly with the hardware device and provides a set of low level hardware specific services. A logical 
device driver (LDD) performs the logical processing that transforms these low level services into the 
high level services used by an application. This two-layer nature of device drivers at Psion can be 
illustrated by the following example. An application using the serial driver decides that it requires 
RTS/CTS handshaking. It calls an LDD which decides whether or not a line should be driven. If the 
answer is yes, the LDD calls the appropriate PDD and asks for a particular line to be driven to a 
specific state. The PDD duly carries out the requested service. Psion SIBO machines often use the 
same LDD with a PDD written specifically for each version of the hardware device. In such a 
situation, splitting the device driver is highly desirable. In the example given above, however, the 
LDD could have talked directly with the hardware negating the requirement for a separate PDD. 
Similarly, most external peripherals would normally use an LDD. 


An LDD must provide a minimum of eight functions for use by the operating system. The functions 
are passed to the OS via a table of function offsets (referred to as the vector function table). These 
functions are mandatory. Similarly, a PDD must provide two functions for use by the operating 
system and may provide more if required. An LDD will usually provide further services/functions for 
use by an application. The form these take is dependent on the LDD requirements and the functions 
supplied by the associated PDD(s). 


Revision 1.00 Page 37 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Psion SIBO machines are supplied with a set of resident device drivers built into the ROM each of 
which can be replaced with an installable device driver having the same name. Installable device 
drivers can also be added to increase the number of available device drivers. Installing a device driver 
is carried out dynamically without resetting the machine (this is not the case with many operating 
systems). 


Device Names and Channels 


The name of a device driver is the mechanism by which an application can obtain a channel to that 
device driver. A logical device driver name always has three characters followed by a colon. For 
example, "TTy:" is the serial LDD. This name is required to uniquely identify the LDD to the EPOC 
OS when attempting to open a channel on it. A physical device driver name always has the three 
characters of its owning LDD followed by a period, a further three characters and a colon. For 
example "TTy.UAR" is the ASICS UART driver and "TTy.srRx" is the 16450/16550 driver. The first 
three characters of a PDD name are the name of the LDD to which the PDD belongs. The second set 
of three characters uniquely identify the PDD. Thus in the above examples, both PDDs belong to the 
"tty:" LDD. 


A channel can be opened on an LDD by calling the PLIB library function p_open. EPOC uses the 
driver name passed through an application p_open call to invoke the IoOpen operating system 
service. This service in turn calls the associated driver ‘open vector’ which can decide whether or not 
to open a channel on the driver. The assembled ASIC4 Example Interface Board logical device 
driver, A4EXIF.LDD, for example, has the three-character device name "LED" so a channel with its 
handle in pcb may be obtained on it by means of the following call: 


p_open(&pcb, "LED:", -1) 


In this call, the third argument refers to the open mode and a value of -1 indicates that the mode 
parameter is to be ignored. To obtain a channel on a PDD, an application should call the DevopenPpp 
OS service. Typically, only LDDs open PDDs though the p_open library function can be used to open 
a PDD indirectly as illustrated in the following example: 


p_open(&pcb, “"TTY.UAR:", -1) 


For a device driver configuration consisting of an LDD and a PDD, the application will usually open 
a channel to the LDD only: the LDD as part of its initialisation would open a channel to the required 
PDD. If an LDD requires a PDD and none is specified, it is up to the LDD to either fail the open 
request or hunt for a loaded PDD that it can use. An LDD uses the DevFind OS service to search for 
a PDD as for instance in the case of the "TTy:" device. 


A device driver may be capable of supporting more than one open expansion channel at a time. In 
order to distinguish the channels, a qualifier can be added to the open request as part of the device 
name. It is then up to the device driver to specify the format of the qualifier. By convention, 
channels are allocated a single character sequentially from the character 'A'. For example, the 
parallel port driver can support two open channel, 'A' and 'B'. The LDD requires one of these 
qualifiers in order to open a parallel driver channel: 


p_open(&pcb, "PAR:A", -1) 
p_open(&pcb, "PAR:B", -1) 


The number of channels that can be thus supported will in general be dependent on the host SIBO 
hardware. In the case of the serial port on the S3a, for instance, only one SIBO channel can 
legitimately be opened corresponding to expansion port C. With the Workabout and HC, however, it 
is possible to open up to three separate SIBO channels on ports A through to C where A refers to the 
top port of the host machine, B to the bottom port and C to the side (or cradle) port. 


LDDs have been designed to be accessed via the I/O system. I/O requests on the opened channel will 
reach the 'strategy vector' of the device driver. PDDs have been designed to be accessed by an LDD 


Revision 1.00 Page 38 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


either via far calls or the Devvector OS system service. Once a channel has been obtained on a 
device driver, the operating system can send it events not sent to other applications. Examples are 
events generated by the machine being switched on or off, memory segments being moved about and 
the owning application being panicked. The EPOC OS can handle a maximum of 32 device drivers 
on a Series3 machine and 48 on other machines. 


Loadable Logical Device Driver Structure 


Common features of the structure of loadable LDDs 


All loadable LDDs must conform to the following rules: 

e There must be a single code segment and no data segments. The code segment is encapsulated in 
the assembler .asm file by calls to the codeSeg and EndCodeSeg defines respectively. 

e The code segment must begin with a LibEnt structure which indicates the LDD name or 
signature which is used to identify the driver when trying to open and close channels. 

e There must be at least eight supported functions which are listed in the LibEnt struc. 


LibEnt Structure 


The first field of the LibEnt structure consists of a two-byte signature containing the define 
‘LDDSignature’ or 'PDDSignature’ in the case of a PDD. The remaining fields consist of an eight 
byte name which holds the device driver name stored as a zero terminated string (note that the 
trailing colon is omitted), a two byte vector count which must be at least eight and a vector table 
listing the supported device driver functions. The relevant code in the case of a hypothetical DevFunc 
LDD (DEVFUNC.LDD) with the device name of "TES:" is listed below: 


CodeSeg 


ProcBegin@ DevFuncLDD 


dw LDDSignature 
db 'TES',0,0,0,0,0 
dw (VectorEnd-Vector) /2 
Vector: 
dw DevFuncInstall 
dw DevFuncRemove 
dw DevFuncHold 
dw DevFuncResume ; Mandatory LDD vectors 
dw DevFuncReset ; must be in this order 
dw DevFuncUnits 
dw DevFuncOpen 
dw DevFuncStrategy 
VectorHandler: 
dw DevFuncHandler ; Optional LDD vectors 
InterruptVectors: 
dw DevFuncTickInt 
VectorEnd: 


ProcEnd noret 
The vector table contains the offsets within the device drivers code segment for the functions required 


by the EPOC operating system which must be entered in the order shown. Note that in this 
document, the terms vector and function are used interchangeably. 


Mandatory LDD Functions 


All LDDs must support the following eight functions: 


@ DevFuncInstall called on device installation 

@ DevFuncRemove called on device removal 

@ DevFuncHold called to temporarily disable the driver 

@ DevFuncResume called to enable the driver after it has been temporarily disabled 


Revision 1.00 Page 39 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


@ DevFuncReset called when an application terminates without closing the channel 
@ DevFuncUnits called to query the number of supported units (i.e. channels) 

@ DevFuncOpen called to open a channel to an LDD 

@ DevFuncStrategy called to access the driver's functionality from the I/O system 


All of the eight mandatory routines pointed at by the function vector table will be called FAR by the 
operating system and should therefore use a FAR return machine code instruction to return control 
back to the OS. Since the FAR return address is to the OS it does not matter if the OS moves memory 
whilst code in the LDD is being executed: the OS cannot move its own code. 


DevFunclinstall 


This function is called by the operating system when the device driver is loaded in order to initialise 
any internal variables. It should not be called directly by an application process. The DevInstall 
operating system service will cause this function to be called. Applications should not call this service 
directly and should call instead the DevLoadLDD service. 


An installable device driver may have the same name as a resident device driver. When the operating 
system loads a device driver, it places it at the end of the device driver table. The operating system 
will search this table for the appropriate device driver when it wishes to establish a channel. The 
search starts at the end and thus will locate the most recently installed device driver (if any) or if not, 
the resident driver. By this mechanism an installable driver can replace any resident driver. 

When called, the DS and ES segment registers are in an unknown state. The device driver should 
take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers 
this involves setting the DS and ES registers to the CS register or more commonly just using the CS 
override. The operating system will not move memory whilst in this function, thus the normal rules 
governing DS and ES may be ignored. All operating system services may be called, except those 
concerning file or device access. 

PASSED 

No values are passed to the install vector. 

RETURN 

If the installation was successful, return with the carry flag clear. 

If the installation failed, return with the carry flag set and the error number in the AL register. 
PANIC 

The install vector must not panic: it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the install function. 


DevFuncRemove 


This function will be called by the operating system when the device driver is requested to be 
unloaded. It should not be called directly by an application process. The DevRemove operating system 
service will cause this function to be called. Applications should not call this directly, they should use 
the DevDelete service. Before the remove function is requested, the device driver will have received 
a hold request. Thus devices will only ever be removed when in a held state. If the device driver is 
currently busy serving a client, the remove request should return an error. Note that all resident 
device drivers will return an error since there is no mechanism by which they can be re-installed. 


When called, the DS and ES segment registers are in an unknown state; the device driver should take 
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this 
involves setting the DS and ES registers to the CS register. The operating system will not move 
memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All 
operating system services may be called inside the remove vector, except those concerning file or 
device access. 

PASSED 

No values are passed to the remove vector. 

RETURN 

If the remove was successful, return with the carry flag clear. 

If the remove failed, return with the carry flag set and the error number in the AL register. 


Revision 1.00 Page 40 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


PANIC 

The remove vector must not panic: it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the remove vector. 


DevFuncHold 


This vector will be called by the operating system when a logical device driver is requested to be held. 
The hold vector is called in the context of the operating system so DS and ES are not available. The 
DevHold operating system service will cause this vector to be called. Applications should not call this 
service. Physical device drivers cannot invoke holds and resumes. The operating system will call the 
hold vector under three conditions: 

e Device memory segments are about to be moved. 


e The machine is about to switch off due to the auto switch off time-out or user request, it 
enters the standby state. 


e The machine is about to switch off due to the power source being removed. 


It should be noted that holds and resumes are called on a per driver basis and so the corresponding 
driver code must deal with all the currently open channels. In all cases the device driver must 
respond to the request as quickly as possible. It must also ensure that ALL interrupts from the 
hardware device that it is driving are disabled. Device memory segments can only be moved if an 
installable device driver is being installed or removed. If the LDD uses an attached PDD and uses the 
faster FAR call mechanism to call the PDD strategy vector, the PDD strategy vector address will 
potentially move, thus the FAR address will be wrong. This address can be resolved in the resume 
vector. The LDD must not call the PDD between a hold and resume. Typically, the device driver 
only needs to disable its interrupts. When a resume occurs, the device driver should continue as 
though nothing had happened. 


If the machine is about to switch off due to the auto switch off or user request mechanisms (enter the 
standby state), the device driver should make an orderly shut down of the device such that the state 
before the shut down can be recovered when the system powers up again. The device driver should 
also attempt to ensure that no data is lost. For example, in the serial driver the current state of the 
hardware handshaking lines should be noted so that each state can be restored on power up. For this 
type of power down the hold vector is allowed to take a significant length of time to shut down a 
device. For example in a serial driver the hold vector should wait until the remote end stops 
transmitting data after any hardware handshaking has been applied. Of course, the time taken should 
be kept to a minimum: in the case of the serial driver above the time is roughly equivalent to 3 
character transmission times. When a resume occurs the device driver should continue as though 
nothing had happened. 


If the machine is about to switch off due to the power source being removed, the device driver should 
reset the device in the minimum possible time: no attempt should be made to perform an orderly shut- 
down. The device driver is not expected to be able to recover the hardware state. When a resume 
occurs, the device driver would typically fail any outstanding application requests. If the hold vector 
takes too long the voltage will fall below the threshold to hold the state of the internal RAM. If this 
occurs the machine will perform a warm re-boot when powering up, all data in the internal memory 
of the machine will be lost including the device driver code! On power fail there is about 2ms 
available to power down all devices. 


On a power failure hold, the operating system will already have sent a 'reset' to all the SIBO serial 
channels. Any device drivers using these channels need only record the hold reason for the resume 
vector. Any other peripherals should be designed to allow a power fail mechanism with the minimum 
amount of code. It must be noted that the power fail type hold can occur whilst the device driver is in 
the memory move hold state. In this case, the device driver will receive two hold requests before 
seeing a resume request. A device driver must be capable of handling this. In this case, the device 
driver will also receive two resume requests. A device driver will not get a power fail hold whilst in 


Revision 1.00 Page 41 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


power down hold. A call to the hold vector will always be followed by a call to the resume vector 
(except when a device is requested to be removed). 


Note that with the Series 3a and Workabout, there is an additional case when hold and resume must 
be invoked and that is on opening/closing of the pack doors. In this case, the LDD must generate its 
own Hold and Resume. This situation is examined in more depth in the context of the specific 
example drivers presented later in this document. 


When called, the DS and ES segment registers are in an unknown state; the device driver should take 
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this 
involves setting the DS and ES registers to the CS register. The device driver should not call any 
operating system services in the hold vector code due to the time taken, especially on power failure. 
PASSED 

The AH register takes one of the following 


@ DevHoldNormal Device memory is about to be moved. 
@ DevHoldPowerDown The system is about to enter the standby state. 
@ DevHoldPowerFail The system has lost its power supply. 
RETURN 
None. 
PANIC 


The hold vector must not panic: it will cause an operating system kernel fault if it does. 
PRESERVE 
The SS, SP and BP registers must be preserved by the hold vector. 


DevFuncResume 


This vector will be called by the operating system when the device driver is requested to be resumed. 
The resume vector is called in the context of the operating system. The DevResume operating system 
service will cause this vector to be called. Applications should not call this service. The resume 
vector will be called either when memory has finished being moved or when the machine powers back 
up. In both cases the hold vector will have been called before this vector is called. The device driver 
is expected to recover from the previous hold request (except power fail) and resume any I/O that was 
suspended. If the device driver has an interrupt service routine, it should reset the interrupt service 
routine's address since the device driver may have moved in memory; its absolute segment address 
will be different. 


If the hold was a device memory segment move type hold, interrupts should be re-enabled. If the 
LDD uses an attached PDD and uses the FAR call mechanism to access the PDD strategy vector, the 
address of the PDD should be reset by using the DevGet PDDAddress operating system service before 
enabling interrupts. Typically, the PDD will have a call back to the LDD and it needs to be informed 
of the change of address of the LDD call back function, the LDD-PDD interface definition should 
allow such a function request. 


If the hold was a power down type hold, the resume vector needs to power up the peripheral and set it 
to the state that it was in before the power down occurred. If this is not possible or data has been lost, 
the device driver should inform any outstanding requests of this fact. It is also possible that the 
hardware device that the driver is associated with has been removed. The driver should be able to 
handle this properly. If the device driver is expected to generate events due to an external state 
change, the driver should check the external state and generate appropriate events. For example, the 
serial driver may be requested to inform an application when the DTR line changes state. The remote 
end may have changed the state of DTR whilst the driver is held. 


If the hold was a power failure type hold, the resume vector should power up the peripheral and put it 


into a known state, preferably the state that the application software thinks that the device is in and 
fail any outstanding requests as data is quite likely to have been lost. 


Revision 1.00 Page 42 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


When called, the DS and ES segment registers are in an unknown state. The device driver should 
take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers 
this involves setting the DS and ES registers to the CS register. All operating system services may be 
called, except those concerning file or device access. 

PASSED 

None 

RETURN 

None. 

PANIC 

The resume vector must not panic, it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the resume vector. 


DevFuncReset 


This function will be called by the operating system when the device driver is requested to reset a 
channel. The reset function is called in the context of the operating system so DS and ES are not 
available. The device driver must request that the operating system call the reset function. This is 
achieved by calling the IoRequestReset system service, usually in the open vector. To cancel this 
request, the device driver should call the IoRequestResetCancel system service. The cancel service 
is usually called as part of the close functionality in the strategy vector. The reset vector will be called 
when the operating system is tidying up resources owned by a process that has terminated. Ifa 
process terminated before it closed the device driver channel and no reset service is requested, that 
channel would remain allocated; no process will ever close the channel. The reset vector allows a 
device driver to reset itself and allow the channel to be opened again. Any data required to perform 
the reset must be stored in the device driver. The data space belonging to the process that originally 
opened the channel has been returned to the operating system memory pool and is no longer valid. If 
a device driver can handle multiple channels then the data passed to the IoRequestReset system 
service should identify the channel. This data will be passed in the CX register to the reset vector. 
The device driver should only have a reset request outstanding with the operating system while a 
process has a channel open. 


When called, the DS and ES segment registers are in an unknown state; the device driver should take 
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this 
involves setting the DS and ES registers to the CS register or using CS override. All operating system 
services may be called, except those concerning file or device access. 

PASSED 

This function is passed data in the CX register that the device driver requested it be sent to determine 
which channel should be reset. 

RETURN 

None. 

PANIC 

The reset vector must not panic; it will cause an operating system kernel fault if it does. 

PRESERVE 

The SS, SP and BP registers must be preserved by the reset vector. 


DevFuncUnits 


This function will be called by the operating system when the device driver is requested to report the 
number of units (i.e. channels) the device driver can support. This function is called in the context of 
the operating system. The operating system places no significance on the number of channels a 
device driver can support. It is primarily used for informational purposes. An application may use 
the number of units to attempt to open any available channel on that device driver. 


When called, the DS and ES segment registers are in an unknown state; the device driver should take 
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this 
involves setting the DS and ES registers to the CS register. All operating system services may be 
called, except those concerning file or device access. 

PASSED 


Revision 1.00 Page 43 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


None. 


RETURN 

The AX register should contain the number of channels supported. If a device driver can support 
multiple channels (limited only by memory constraints) then the driver may return -1. A serial device 
driver, for example, might only support two channels (TTY:a and TTy:8) whereas the file device 
driver can open an unlimited number of files. 

PANIC 

The channels units vector must not panic; it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the units vector. 


DevFuncOpen 


This function will be called by the operating system when a channel to the device driver is required to 
be opened. This function is called in the context of the process that called the Ioopen system service. 
This means that DS and ES point to the application data space. The device driver is passed two 
parameters, its device handle and a pointer to an OpenEnt structure. The device handle is the entry in 
the system device table of this device driver. The device driver is required to place this handle in the 
ChanLibHandle field of the ChanEnt structure which must be allocated in the user's data space. The 
operating system uses the device handle to route any I/O requests on the opened channel to the correct 
device driver. 


The OpenEnt structure contains three fields, openNamePtr, OpenMode and OpenChan. 

The openNamePt r field contains a pointer to the character that exists after the device name as passed 
to the ToOpen system service. For example, if the ToOpen service was passed a name of PAR:A, the 
OpenNamePtr field would point to the colon. If the ToOpen service was passed a name of TTY.AS5:B 
the OpenNamePtr field would point to the full stop. The device driver should process the name 
appropriately, opening the correct PDD as required. 

The OpenMode field contains the mode for opening the device driver. The available modes are 
specified by the device driver writers. For example, a combined Xmodem and Ymodem device driver 
could use the mode to specify whether the Xmodem or the Ymodem protocol is to be used. 

The Openchan field contains the I/O channel handle of the device that this driver is required to 
‘attach’ to. Attached device drivers are dealt with later in the chapter. 

The code in a device driver open vector tends to follow a very similar pattern. This is demonstrated 
by the following code fragments and associated comments. The first stage is to allocate some data 
space in the calling process' heap space. This will contain the I/O channel control block: 


mov cx, (size DeviceEnt) 

HeapAllocateCell 

jc noMemory 

mov bx, ax ; cell handle 


If the device driver requires a WaitHandler (described later): 


mov al, (VectorHandler-Vector) /2 
ToAddHandler 

jc endFreeMemory 

mov [bx].DriverHandler, ax 


If the device driver's DevFuncReset vector is required to be called: 


push bx 

mov cx, ChannelIndicator 7 unique per channel 
mov bx, ax ; the device handle 
ToRequestReset 

pop bx ; restore alloc cell 


The chanEnt field of the DriverEnt structure must be initialised: 


mov [bx] .DriverIo.ChanNext, bx 
mov [bx] .DriverIo.ChanSignature, IoChanSignature 
mov [bx] .DriverIo.ChanLibHandle, dx 


The ChanNext field is used by attached drivers and will usually be set to be the allocated cell handle 
of the device driver being opened. The IoFuncattach and IoFuncDetach functions manipulate these 
fields. The I/O system uses this field to direct the I/O request to the correct driver. 


Revision 1.00 Page 44 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The ChanSignature field is checked by the operating system during any I/O requests for the value 
IoChanSignature. If it does not contain that value, the process calling the I/O service will be 
panicked for having passed an invalid I/O channel handle. 

The ChanLibHandle field is used by the operating system to route an application's I/O request to this 
device. The I/O request will call the DevFuncstrategy vector of the device driver. 

If the driver is an attached driver the following is required: 


mov cx, bx ; allocated channel 

mov bx, [si] .OpenChan ; channel attaching to 
mov al, IoFuncAttach ; return in BX the 
ToWithWait ; channel attached to 


Finally, if the channel has been successfully opened: 
ele Opened Ok 
ret return BX and DX 


’ 


’ 


The error recovery code typically follows the following pattern: 


endFreeReset: 
push ax 
push bx 
mov cx, ChannelIndicator 
mov bx, ax 
ToRequestResetCancel 
pop bx 
pop ax 
endFreeHandler: 
push ax 
push bx 
mov bx, [bx] .DriverHandler 
ToRemoveHandler 
pop bx 
pop ax 
endFreeMemory: 
push ax 
HeapFreeCell 
pop ax 
stc 
noMemory: 
ret 


If a device driver supports a fixed number of channels, it typically contains static control blocks. In 
order to determine if a requested channel is currently open, a field should be interrogated. The device 
driver should ensure that interrupts are disabled during this sort of check since a context switch could 
occur and another process request the opening of the same channel. This is the classic 'test and set' 
problem encountered in multi-tasking environments. 


When called, the DS and ES segment registers point to the data segment of the application process 
attempting to open a device channel. The application should ensure that the DS and ES segment 
registers do in fact point to its data segment. The device driver must obey the normal rules 
concerning segment register manipulation. The DS and ES segment registers can be reloaded if 
required from the IntEnt structure pointed at by the BP register. All operating system services may 
be called. 

PASSED 

DX contains the device handle of the device driver. 

SI is a pointer to the OpenEnt structure 

BP is a pointer to the IntEnt structure. 

RETURN 

If the channel open was successful, return with the carry flag clear and the BX register containing the 
open channel. 

If the open failed, return with the carry flag set and the error number in the AL register. 

PANIC 

The open vector can panic; it will cause the process requesting the device open to terminate. It is 
however more usual to return an error to the calling process. 

PRESERVE 

The DS, ES, SS, SP, BP and DX registers must be preserved by the open vector. 


Revision 1.00 Page 45 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


DevFuncStrategy 


When an application makes an I/O request on the opened device driver channel the request is routed 
to this vector by the operating system. A device driver defines the set of functions that it supports. 
These typically include IoFuncSet, IoFuncSense, IoFuncRead, IoFuncWrite and IoFuncClose. A 
device driver does not have to support any particular function, as it is a matter of design between a 
device driver writer and application writer as to what functions and associated parameters are 
provided. To obtain the power of attached device drivers, however, it is recommended that the device 
driver use the system defines with their appropriate functionality, for example, the loFuncWrite 
function number should always be associated with writing data. 


The strategy function is passed the channel handle as allocated in the open vector in the BX register. 
This typically contains control information concerning the current state of the I/O channel. 

The SI register contains a pointer to a RgEnt structure. This structure contains four fields, 
RqFunction, RqStatusPtr, RqA1Ptr and RqA2Ptr. 

The RgFunction field contains the function number as passed to the IowithWait (or 
IoAsynchronous) I/O request by the application. If a device driver does not support the specified 
function, it should pass the request on to its 'parent' device driver. 

The RqStatus pointer contains a pointer to a memory location in the application process's data space 
that receives the I/O requests completion status. The device driver must set this memory location to 
the value PendingErr whilst the I/O request is outstanding and a completion code when the I/O 
request completes. An I/O request may complete within the strategy vector or it may complete some 
time in the future, presumably from some interrupt. 

The RgA1Ptr and RqA2Ptr fields contain the argument | and 2 parameters as passed to the 
IoWithWait (or IoAsynchronous) system services. The device driver is free to specify what these 
parameters are (if any). 


The operating system defines a set of common function numbers used by device drivers referred to as 
the IoFuncxxx set of defines. By convention, a device driver should select from this list, particularly 
if some of the more advanced features of the I/O system are to be used, such as attached device 
drivers. The more common defines are listed below: 


@ ToFuncRead ; read from the device. 

® TfoFuncWrite ; write to the device. 

@ TloFuncClose ; close device channel. 

@ = =ToFuncCancel ; cancel an I/O request. 

® ToFuncSet ; set driver characteristics. 

® tloFuncSense ; sense driver characteristics. 
e lIoFuncFlush ; flush any buffers. 


The PLIB library functions p_read, p_write and p_close will call the device driver with the 
IoFuncRead, IoFuncWrite and IoFuncClose function numbers. Thus, if the device driver chooses 
an alternative function number set, an application will not be able to use the supplied library 
functions. All resident device drivers obey the following conventions: 
e Acancel request will cancel any outstanding requests. A cancel request will not return any 
error. 


e Aclose request will ensure that any outstanding requests are completed before closing the 
channel. A close request will not return any error. 


e Only one request of a particular type can be outstanding at any one time. If a second request 
is made the device driver will panic the calling application. 


Any functions that the strategy function does not support should be passed on to the next driver down 
the driver hierarchy. If the driver is a root driver (attached driver), this is achieved using the IoRoot 


Revision 1.00 Page 46 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


(IoSuper)system service. If the requested function is not supported by any driver, the operating 
system will return a Not Supported error. 


When called, the DS and ES segment registers point to the data segment of the application process 
making the I/O function request. The application should ensure that the DS and ES segment registers 
do in fact point to its data segment. The device driver must obey the normal rules concerning 
segment register manipulation. The DS and ES segment registers can be reloaded if required from 
the IntEnt structure pointed at by the BP register. All operating system services may be called. 
PASSED 

BX contains the allocated channel control block. 

DX contains the device handle of the device driver. 

SI is a pointer to the RqEnt structure. 

BP is a pointer to the IntEnt structure. 

RETURN 

If the function request is successful, the strategy vector should return with carry clear. A request 
typically causes some I/O. If the I/O is completed by the strategy vector (i.e. the request is for a 
synchronous function such as close), the completion status should be written back to the RqStatusPtr 
location and the I/O semaphore signalled (using the IoSignal system service). If the request has not 
yet completed (i.e. the request is for an asynchronous function), the RqStatusPtr location should 
contain the value PendingErr and the I/O semaphore should not be signalled. 

If the function request failed the strategy vector should return with carry set and the error code in AL. 
In this case, typically no I/O requests will be completed. 

PANIC 

The strategy vector can panic; it will cause the process making the I/O request to terminate. In most 
cases it is usual to return an error to the calling process. A major exception to this is if the calling 
process makes an I/O request of the same type as one that is currently outstanding and the device 
driver only supports one I/O request of a particular type at a time; by convention the device driver 
should panic the calling process with the PanicIoPending panic code. 

PRESERVE 

The DS, ES, SS, SP and BP registers must be preserved by the strategy vector. 


Interrupts and Interrupt Service Routines 


Device drivers that talk to hardware tend to have interrupt service routines associated with them, 
especially if they are receiving data from an external source. The EPOC operating system provides a 
framework within which an interrupt service routine can be written relatively easily. An interrupt 
service routine is a code section that is called by the OS in response to a particular hardware event. 
As indicated in the Hardware Overview, the SIBO architecture allows for eight independent hardware 
interrupt sources, some of which are pre-allocated to system components. The operating system 
provides the GenSetRevector service to allow a device driver to install an interrupt service routine 
for any of the eight hardware interrupt sources. This call passes the interrupt vector (the address of 
the interrupt service routine) and the interrupt number (which is dependent on the host hardware) to 
the OS so that it knows where to jump to when the interrupt occurs. A device driver should use this 
system service and not poke directly into the 8086 interrupt vector table. The address passed to the 
GenSetRevector Service is not written into the interrupt vector table but to an internal table. After 
invoking this service, the desired interrupts must be masked in by writing the appropriate mask to the 
mask register. Initially, of the eight interrupt sources, only the tick interrupt is masked in. 


When an interrupt occurs, the microprocessor could be running any currently active process. The OS 
handles the servicing of interrupts by building a mandatory operating system call frame. All CPU 
registers are preserved on route. The interrupt service routine is then called as a FAR routine. Since 
the operating system preserves all registers the interrupt service routine is free to use any register. As 
with all interrupt service routines various rules apply: 


e Interrupt service routines should execute as fast as possible. Operating system interrupt 
service routines are tuned to last no longer than one millisecond. 


Revision 1.00 Page 47 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


e Typically, interrupt service routines do not enable interrupts unless the routine can handle re- 
entrancy. 


e Interrupt service routines run in the context of whatever process is running at the time of the 
interrupt. An interrupt service routine should not attempt to obtain admissibility to the 
process that opened the channel but access the internal driver space only which in general is 
its own code space. 


e An interrupt service routine must not directly cause the OS to reschedule the running process 
as this would significantly delay its completion. It must use the IoSignalByPidNoReSched system 
service in order to indicate to the handler that an event has occurred to the owning process. 
The handler function of the device driver must pick up the event and inform the owning 
process. 


e An interrupt service routine should return with the carry flag clear if it requires a reschedule 
to occur (it has called IoSignalByPidNoReSched) otherwise return with the carry flag set. This 
will cause the operating system to reschedule if the internal state allows such an action 
otherwise the reschedule request is effectively queued until such time that the operating 
system can reschedule. 


At some stage during the course of an interrupt service routine, it is necessary to clear the interrupt 
line with some hardware-specific action. Then the interrupt controller inside the host ASIC1 or 
ASIC9 has to be cleared with a write to the NonSpecificEoi location. To remove the interrupt service 
routine address, the operating system service GenResetRevector should be used. This will reset the 
internal table entry to the default held in the ROM. Additionally, the interrupt mask should be reset 
to the original value. 


Device Driver I/O Semaphore Wait Handlers 


An LDD may nominate one of its functions to be called by the operating system every time the I/O 
semaphore of the process that opened the channel is signalled. The nominated function, known as the 
wait handler, will only be called if the application is waiting for an outstanding I/O request to 
complete. For well written applications this is practically all the time. By convention the vector table 
entry after the mandatory vectors contains the handler vector. A handler routine is similar to an 
interrupt service routine in that it appears to run ‘from nowhere’. Comparing handlers and interrupt 
services routines shows that: 


e A handler will always run in the context of the process that has opened a channel. An 
interrupt service routine will run in the context of whatever process happens to be running at 
the time of the interrupt. 


e A handler can access the data space of the process that opened the channel. The interrupt 
service routine must not. An interrupt service routine should only access the data space in 
the driver which is usually its own CS space. 


e A handler can cause a reschedule. An interrupt service routine must not cause a reschedule. 
If it did, the interrupt would not be fully serviced (the rest of the interrupt service routine 
would not be executed until a reschedule back to the process running at the time of the 
interrupt, which may not happen for a significant length of time). The interrupt service 
routine must only use the IoSignalByPidNoReSched to signal the channel owner. 


The handler is the mechanism by which hardware interrupt events can be filtered through to the 
process using the I/O channel. Typically, it is in the handler code that the 1oSignal signifying 
completion of an asynchronous I/O request is invoked. 


Loadable Physical Device Driver Structure 


A loadable PDD must obey the following rules: 
e There must be a single code segment and no data segments. 


Revision 1.00 Page 48 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


e The code segment must start with a LibEnt structure. 
e There must be at least two supported functions, with typically a further two defined. 


Single Code Segment 


A PDD must be written to contain any internal variables within its own code segment. Typically, 
these variables are only concerned with unit (i.e. channel) allocation and hardware state. Data space 
for a particular open channel can be allocated in the heap space of the process that opens the device. 
This data space will however disappear if the process terminates, thus any variables required for 
‘freeing’ the hardware after a process terminates must exist in the code space of the device driver. 


The LibEnt Structure 


A LibEnt structure has the following format: 
e =A two byte signature 


e §=6©An eight byte name 
e A two byte vector count 
e A vector table 


The two byte signature should contain the 'PDDSignature' define. The eight byte name contains a 
zero terminated name, being that of the device driver. Note that there is no trailing colon. The two 
byte vector count contains the number of vectors that follow immediately after the count. There 
should be at least two. For example: 


dw PDDSignature ; Its an PDD driver 

db "DVR.HW1',0 ; Name of the driver 

dw (VectorEnd-Vector)/2 ; Number of vectors 
Vector: 

dw DvriInstall ; Install vector 

dw DvrRemove ; Remove vector 
VectorEnd: 


Most PDDs also define a further two vectors: 
dw DvrOpen , Open Vector 
dw DvrStrategy ; Strategy vector 


The table of vectors is a table of offsets within the device drivers code segment of the routines that 
implement the required functionality. The vector table must have the entries in the order shown in 
the example. 


Mandatory PDD functions 


All PDDs must support the following two functions: 
@ DevFuncInstallppp called on device installation. 


@ DevFuncRemovePDD called on device removal. 


Most PDDs will support the following two additional functions: 
@ DevFuncOpenPDD called to open a PDD. 


@ DevFuncStrategyPDD called to provide PDD functionality. 


All of the routines pointed at by the function vector table will be called FAR by the operating system 
and should consequently use a FAR return machine code instruction to return back to the operating 
system. Since the FAR return address is to the operating system, it does not matter if the operating 
system moves memory whilst code in the LDD is being executed; the operating system cannot move. 


DevFunclnstallPDD 


This vector will be called by the operating system when the device driver is loaded to initialise any of 
its internal variables. The install vector is called in the context of the operating system and not the 
process that is loading the device driver. The DevInstall operating system service will cause this 


Revision 1.00 Page 49 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


vector to be called. Applications should not call this directly, they should use the DevLoadPDD 
service. 


An installable device driver may have the same name as a currently installed device driver. When 
installed, the driver is added to the end of the device driver table. When a channel to a device driver 
is being established by the operating system, it searches the device table from the end first, thus the 
latest installed device driver with the required name will be asked first for a channel. So as with 
LDDs by this mechanism installable device drivers can replace any of the resident drivers. 


When called, the DS and ES segment registers are in an unknown state. The device driver should 
take whatever steps necessary to obtain direct addressability to its data. For loadable device drivers 
this involves setting the DS and ES registers to the CS register. The operating system will not move 
memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All 
operating system services may be called except those concerning file or device access. 

PASSED 

No values are passed to the install vector. 

RETURN 

If the installation was successful, return with the carry flag clear. 

If the installation failed, return with the carry flag set and the error number in the AL register. 
PANIC 

The install vector must not panic; it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the install vector. 


DevFuncRemovePDD 


This vector will be called by the operating system when the device driver is requested to be unloaded. 
The remove vector is called in the context of the operating system and not the process that requests 
the unload. The DevRemove operating system service will cause this vector to be called. Applications 
should not call this service directly; instead, they should call the DevDelete service. Before the 
remove function is requested, the operating system will send a DevFuncHold request to all LDDs. 
The LDD is responsible for ensuring that no activity will occur during the remove. Note that any 
device driver that handles hardware interrupts must contain an LDD since only LDDs receive a hold 
request. If the device driver is currently busy serving a client, the remove request should return an 
error. All resident device drivers will return an error since there is no mechanism by which they can 
be re-installed. 


When called, the DS and ES segment registers are in an unknown state; the device driver should take 
whatever steps necessary to obtain direct addressability to its data. For loadable device drivers this 
involves setting the DS and ES registers to the CS register. The operating system will not move 
memory whilst in this function, thus the normal rules governing DS and ES may be ignored. All 
operating system services may be called except those concerning file or device access. 

PASSED 

No values are passed to the remove vector. 

RETURN 

If the remove was successful, return with the carry flag clear. 

If the remove failed, return with the carry flag set and the error number in the AL register. 
PANIC 

The remove vector must not panic; it will cause an operating system kernel fault if it does. 
PRESERVE 

The SS, SP and BP registers must be preserved by the remove vector. 


DevFuncOpenPDD 


This function is defined as a convenience function for the LDD-PDD interface. When an application 
opens a channel to an LDD, it normally uses the Ioopen system service. If the name specifies, or the 
LDD requires, a PDD then it needs to open a channel toa PDD. The Devopenppp system service will 
call this PDD vector to establish a channel. The LDD now has a choice of calling a PDD vector using 
the DevVector system service or calling the fourth vector in the vector table directly. The fourth 


Revision 1.00 Page 50 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


vector is assumed to be a strategy vector to which any parameters as required by the LDD-PDD 
interface can be passed. The FAR address of the strategy vector is returned by the 
DevGetPDDAddress. When an LDD receives a DevFuncResume it should call DevGet PDDAddress 
again to ensure that if the PDD has moved the LDD still has its correct address. As a design, a PDD 
could provide many vectors, one for each required function. The LDD would then use the Devvector 
system service to access each of these functions. The DevGetPDDAddress will only return the FAR 
address of the fourth vector. 


When called, the DS and ES segment registers point to the data segment of the application process 
making the open function request. The application should ensure that this is indeed the case. The 
device driver must obey the normal rules concerning segment register manipulation. All operating 
system services may be called. 

PASSED 

The BX register contains a pointer to the PDD unit name. The pointer passed to the DevOpenPDD 
service is used to find the PDD device to open. The BX register is loaded with a pointer to the 
trailing colon (if any) in the PDD unit name. For example if the name "TTy.AS5:A" was passed to 
the DevOpenPDD service, BX would contain a pointer to :A upon calling the open vector. 
RETURN 

If the open was successful, return with the carry flag clear. 

If the open failed, return with the carry flag set and the error number in the AL register. 

PANIC 

The open vector can panic; it will cause the process requesting the device open to terminate. It is 
however more usual to return an error to the calling process. 

PRESERVE 

The SS, SP and BP registers must be preserved by the open vector. 


DevFuncStrategyPDD 


This function is defined as a convenience function for the LDD-PDD interface. Typically, all 
application function requests are routed through the strategy vector. To speed the calling interface, 
the DevGet PDDAddress operating system function will return a FAR address of this vector. The 
device driver writer defines all the functions and return values as required. 


When called, the DS and ES segment registers point to the data segment of the application process 
making the function request. The application should ensure that the DS and ES segment registers do 
in fact point to its data segment. The device driver must obey the normal rules concerning segment 
register manipulation. All operating system services may be called. 

PASSED 

The parameters passed are defined by the device driver write. 

RETURN 

All returns are defined by the device driver writer. 

PANIC 

The strategy vector can panic; it will cause the process requesting the function to terminate. It is 
however more usual to return an error to the calling process. 

PRESERVE 

Which registers are preserved is defined by the device driver writer. 


Revision 1.00 Page 51 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


10. ASIC4/ASIC5 BASED DEVICE DRIVERS 


Introduction 


This chapter describes the rules and problems involved in writing a device driver that controls some 
form of ASIC4 or ASICS based hardware. Details concerning the internal organisation of these 
ASICs were presented earlier in chapters 6 and 7. The emphasis is on their use for Series 3a 
applications, though most issues that will be discussed also apply to the Series 3, MC and HC range of 
Psion products. 


In addition to the eight mandatory functions already detailed in the Device Driver Overview chapter, 
an LDD will usually provide additional functionality in the form of further vector table entries 
dependent upon the requirements of its application. Wherever possible, these functions should make 
use of the various pre-defined system defines for services such as reading (p_read) and writing 
(p_write) etc. It should be noted that there is no particular requirement to implement a device 
driver as a separate PDD and LDD and in the case of the example logical device driver 
A4EXIF.LDD, the approach taken is to incorporate both aspects into the one LDD. 


SIBO Hardware Expansion Channels 


The number of SIBO expansion channels supported by the host machine will vary according to the 
particular Psion hardware present. So that a single device driver may be compiled for the different 
host machine possibilities, a number of build flags can be used to set various constants within the 
include files. The hardware options are outlined in the table below: 


SIBO Machine Flags | Number of SIBO serial channels supported Machine Build Flag 


Consumer (S3a) Refers to $3a with ASIC9 only. Supports 1 SIBO channel 
(A) 


ES ae Mat AST lysed SPS PTT 


It should be noted that Psion device drivers should be designed to be easily adapted from machine to 
machine. For a well-written driver, the only change that needs to be made in adapting it for use on 
another Psion machine is the alteration of the build flag at the start of the code. This flag indicates to 
the compiler which SIBO machine flags as well as other variables should be set for the host machine. 
The four most important SIBO machine variables are the channel interrupt mask, the channel 
interrupt number, the channel interrupt vector and the hardware SIBO channel. The channel 
interrupt mask is an eight bit value or'd with the contents of either AlInterruptMask or 
A9BInterruptMask (the mask registers) to initiate interrupts on the relevant channel depending on 
whether the interrupt controller resides in ASIC1 or ASIC9. If this mask is then used in a 
HwGetChannel call, any hardware interrupts on the selected expansion channel will be directed to the 
appropriately coded interrupt service routine. The channel interrupt mask is also required in the 
subsequent HwFreeChannel OS service call and when stopping hardware interrupts. The channel 
interrupt number is a sixteen-bit quantity required by the GenSetRevector and GenResetRevector 
OS system services to indicate to the OS which default interrupt service routine is to be replaced by 
the suitably coded device driver interrupt vector. The channel interrupt vector is a sixteen-bit 
pointer to the location of that interrupt vector in the device driver code. Finally, the hardware SIBO 
channel is used by the HwSelectChannel OS service to direct any SIBO serial control or data frames 


Revision 1.00 Page 52 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


along the appropriate channel. The situation regarding the value of these variables for the expansion 
ports on all current SIBO platforms is illustrated in the table overleaf: 


IW orkabout (Series3) 
a en en an 
Channels 


Controller ASIC |ASIC? ASICO 
Mask Register A9BInterruptMaskRW a a a ae 


IHwIrq2Revector 


mask A9MExpIntA 
(Expansion Port A) 
mask A9MExpIntB 
(Expansion Port B) 
Imask AOMSlave 

(Expansion Port C) 


IHwIrq4Revector 
IHwIrgq5Revector 
IHwIrq2Revector 


ASIC2 


mask ExpIntLeftA 
(Expansion Port A) 
mask ExpIntRightB 
(Expansion Port B) 
mask Asic2Int 
(Expansion Port C) 


IHwIrgq3Revector 
IHwIrq2Revector 
IHwIrq4Revector 


ASIC2 ASIC2 


mask Asic2Int 
(Expansion Port C) 


mask ExpIntLeftA 

(Expansion Port A) 
mask ExpIntRightB 
(Expansion Port B) 


IHwIrgq3Revector 
IHwIrq2Revector 


IHwIrq4Revector 


Ptr 
Channel SelectChannel5. SelectChannel3 IExpChannelLeftA IExpChannelLeftA SelectChannel7 
Hard Select SelectChannel4 ExpChannelRightB = |ExpChannelRightB 

arOWAre Dre’ SelectChannel5 SelectChannel7 


Talking to ASIC4 


All communication to an ASIC4 is via a Psion Serial Link. As explained in the chapter on the SIBO 
serial protocol, two forms of data can be sent and received along this channel. These are control and 
data bytes. Control bytes give specific instructions to ASIC4 and data bytes can either be data sent to 
or from ASIC4 or data given to or taken from peripheral chips in ASIC4's address space. Sending 
and receiving control and data frames down a Psion Serial Channel from a Series 3/HC host is simply 
a matter of IN and OUT instructions to various fixed I/O addresses. Various assembler macros have 
been set up to ease this task and provide machine independence and they are detailed in the appendix. 
These include: 


SCONTOUT Output the control byte held in the AL register 
SDATAIN Input a byte of data and place it in AL 

SDATAOUT Output the data byte in the AL register 

XNOP Wait a short while 

SBUSY Wait while the Psion Serial Link is busy 


Once a piece of peripheral hardware has been designed the appropriate software must be written to 
control it. All hardware devices on Series 3/3a, Workabout and HC machines are controlled by device 
drivers. These act as an interface between a piece of hardware and an application that uses it. The 
following section goes into further detail regarding the methods by which a device driver is able to 
communicate with and thereby control an ASIC4 and ASICS based peripheral. 


ASIC4 Registers 


ASIC4 has eight registers and their functions in mixed (i.e. peripheral) mode are outlined below: 


Register 0: This register is the read/write Data Register that controls the data lines DO-D7 which are 
normally in tri-state mode. Data written to the Data Register is output on DO-D7 during a write cycle 
and data input to the DO-D7 may be read from the register during a read cycle. On reset, this register 
holds the Info Byte and its bits have the following meanings: 


Revision 1.00 Page 53 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Bit No. D7 D6 DS D4 D3 D2 DI DO 
DD DN N S S _ S 


D D_ OD i _ Device type 

0 0 O RAM SSD 

0 oO 1 Intel Flash type 1 

0 1 O Intel Flash type 2 

Oo 1 1 TBS 

1 0 O TBS 

1 0 1 TBS 

1 1 0 Read only SSD (ROM OTP etc.) 
1 1 1 Hardware Write protected SSD 
N N Number of devices 

0 O 1 

0 1 2 

1 0O 3 

| ae | 4 

S S_ S__ Device Size 

0 O O Illegal (Indicates no SSD present) 
0 0 1 32Kbyte 

0 1 O 64Kbyte 

Oo 1 1 128Kbyte 

1 0 O 256Kbyte 

1 0 1 512Kbyte 

1 1 O 1Mbyte 

1 1 1 2Mbyte 


Register 1: This register is both a read and write register. In read mode, it is termed the Input 
Register. The eight bits of this register are then defined as follows: 


The Se, De and Ne bits hold, on reset, the Extended Info Byte which is used in ASIC4 Extended mode 
to define the type of peripheral device as explained later in the section on ASIC4 reset and 
configuration and outlined below: 


M De Ne Se 
1 0 0 90 No peripheral devices 
1 0 O 1 Turbo RS232 serial (16550) 
1 oO 1 O 3Fax 
1 oO 1 1 T.B.S. 
1 1 0O 0 T.B.S. 
1 1 OO 1 T.B.S. 
1 1 1 O T.B.S. 
1 1 1 1 Extended info contained in ROM. 


The X2 bit sets the state of the X2D2 input which is used to indicate whether the device size is 
correct. In M=0 mixed mode, the X2 bit must be low. Inputs In0-In2 hold the current status of the 
three correspondingly named general input lines to ASIC4. 


In write mode, Register 1 is termed the Device Size Register where bits 3-0 (S3-SO) map to the 
settings of the decoder inputs (and hence the peripheral device size) as follows overleaf: 


Revision 1.00 Page 54 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Size Register Decoder Inputs Device Size (bytes) 
S3 S2 S1 SO DCO DC1 DC2 

0 0 0 0 A15 Al6 Al7 32k 

0 0 0 1 Al15 Al6 Al7 32k 

0 0 1 =O Al6 Al7 A18 64k 

0 oO 1 1 Al7 Al18 A19 128k 
0 1 0 0 Al8 Al19 A20 256k 
0 1 0 1 A19 A20 A21 512k 
0 1 1 =O A20 A21 A22 1M 

0 1 1 1 A21 A22 A23 2M 

1 0 0 0 A22 A23 A24 4M 

1 0 O 1 A23 A24 A25 8M 

1 0 1 O A24 A25 A26 16M 

1 oO 1 1 A25 A26 A27 32M 

1 1 0 0 A26 A27 0 64M 

1 1 0 1 A27 0 O 128M 
1 1 1 = O 0 0 O 256M 
1 1 1 1 0 oO O Not Used 


This register defaults to OxOf on reset (i.e. not used). 


Register 2: A write to this register , the Address Increment Register, will increment the addresses 
AO-A3. 


Register3: This register is the write-only Address Register which controls all 28 address lines (AO- 
A27) directly and the eight chip selects (CSO-CS7) indirectly. The address register is written to in 
multi-transfer mode LSByte (ATO) first. There can be up to four bytes written: 


Byte Address lines 
ATO AQ - A7 
ATI A8& - Al5 
AT2 Al6 - A23 
AT3 A24 - A27 


When the first byte is written, all the higher address lines (A8-A27) are reset to 0. Bits 4-6 of AT3 
may be used by the internal address decoder to control the CS outputs CSO-CS3 if appropriate. On 
reset, all bits of this register are cleared. 


Register 4, 5 and 6: Not implemented. 
Register 7: This register is the write only ASIC4 Control Register and holds the following bits: 


Bit: 7 6 5 4 3 2 1 0 
Label: LBO TSTA LTM VPS EDA CSS WRS OES 


Setting the LBO and VPS bits causes the corresponding lines on ASIC4 to be set high enabling them 
to be used as general purpose outputs for peripheral development. OES and WRS control R/W 
accesses. 


Additional ASIC4 Signals 


InO, In1, In2 are general purpose digital inputs. LBO, VPS are general purpose digital outputs. OE, 
WR control Read/Write bus accesses. MCSD, X2D2 should be tied to ground via a 100k resister. 
POR is the reset line. 


Revision 1.00 Page 55 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Talking to ASIC5 


The Psion serial protocol was designed to allow many different peripheral ASICs to lie on the same 
serial channel. Before software can communicate with an ASICS it must first be selected. ASICS 
must be selected in different ways depending on whether it has been configured (in hardware) to 
operate in either Pack or Peripheral mode. In addition to selecting ASICS when it is first used, 
ASICS must be re-selected whenever a hold and resume is generated due to power down, pack doors 
opening or when the peripheral is inserted or removed. ASIC5 will always respond to a select with a 
byte indicating what type of peripheral or pack it is. If there is no ASICS connected to the Psion 
serial link there will obviously be no response (zero is returned) and software must then take the 
appropriate action. To select a peripheral mode ASICS the following code can be used: 


HwNullFrame 

mov al, (SerialSelect or Asic5NormallId) 
SBUSY 

SCONTOUT 

XNOP 

SBUSY 

SDATAIN 

test al,al 

je NoASIC5PeripheralOutThere 


To select a pack mode ASICS the following code can be used. 


HwNullFrame 

mov al, (SerialSelect or Asic5PackId) 
SBUSY 

SCONTOUT 

XNOP 

SBUSY 

SDATAIN 

test al,al 

je NoASIC5PackOut There 


Note that an ASIC4 can pretend to be an ASICS in pack mode and will respond appropriately. 


ASIC5 Registers 


ASICS has sixteen internal registers. To read or write from an ASICS register takes two steps. First 
a control byte must be sent along the Psion serial link to select which register. This should be 
followed by a read or write of the appropriate data value. The sixteen registers are listed in the table 
below. Some can be read and written to and some are read or write only. 


| oO | URW PortAreadandwritedata 
| 6 | RW Interrupt Maskread and write 
| 8 | RW __| UART Status/UART Control register 
| 9 | R/W_| UART Receive/UART transmit holding register_| 
UART Baud rate LSB 

| 13) | OR Barcodereaddata 
| 4 {| ER Synchronous Port2read 


Revision 1.00 Page 56 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Reading from the Port A register causes ASICS to generate a memory access cycle. The value read 
from port A will be the value retrieved from any attached memory or memory mapped peripheral. 
Writing to Port A will cause ASICS to generate a write cycle and write the supplied value to attached 
memory. In both cases the address used for the access will depend on ASICS's mode and the 
configuration of ports B, C, and D. If the UART is enabled (Bit 0 of the port B mode register) 
memory cannot be accessed because port A lines are reused. 


Writing to port B will cause the value written to be latched onto the output lines PBO-PB7 (which 
form address lines AO-A7 for memory access cycles). Reading from this register will return the last 
value written. 


Writing to the port B mode controls various aspects of ASIC5 behaviour. The table below indicates 
the meanings of each bit in the register. When set to operate in counter mode the value output on 
lines PBO-PB7 can be incremented by reading from the port B mode register, post-incremented by 
reading or writing to the port A register or cleared to zero by writing to the Port D and C register. 


| 0 _| 0, Memory mode. 1, Peripheral mode -enables UART____| 
| 6 NotUsed 
— a 


7 Not Used 


POT | Countermode 
POT Latch mode 
Pot | Baud rate outon portB 


When ASICS is in pack mode the first write to the port D and C register will be latched onto lines 
PDO-PD7. In multiwrite mode the second and subsequent data writes will be latched onto port C with 
the following bits in the register forming the following functions. 


| Databit_ | Pin, | Function _| 
a | 


The bit SELO and SEL1 determine which chip select is used when a memory access cycle is generated 
by accessing port A. CSO-CS3 are selected as follows. 


CSO 


CS2 


= 


Revision 1.00 Page 57 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


In peripheral mode a write to the port D and C register will latch the value written onto lines PD1- 
PD7. In peripheral mode the line PDO forms the UART TX line. Setting bit zero in the port C and D 
register therefore has no effect. 


ASICS is capable of generating an interrupt due to various external events. The interrupt mask 
register is used to select which events will generate an interrupt. Writing to the interrupt mask 
register will set the mask to the value written. Reading the interrupt mask register will return the 
current mask. The meanings of each bit in this register is given in the table below. Setting an 
appropriate bit to 1 will enable that events interrupt, clearing to 0 will stop that event from causing an 
interrupt. On reset all events are disabled. 


Bit 
| OP UART CT UART character received 


Synchronous port] character received 
Synchronous port2 character received 
| 6 [PCA Barcode data/general interrupt 


When an interrupt occurs reading the Interrupt Status register will indicate the source of the interrupt. 
The meaning of each bit corresponds directly to each bit in the interrupt mask (see table above). A 
high bit indicates an active interrupt event. 


Reading the Barcode data register returns a byte representing the states of the following lines. 


Communicating with ASIC4 


ASIC4 is capable of operating in several modes. Attached peripherals can contain an ASICS chip 
instead of an ASIC4. Before talking to an ASIC4 you must first ensure that there is an ASIC4 at the 
end of your serial link and you must set ASIC4 into the correct operating mode. You must do this 
when the channel is first obtained to ensure you have the right peripheral to start with, and also 
whenever you get a Hold and Resume due to a power down, Pack doors opening, or the peripheral 
being removed. You should also check the peripherals ID to check what peripheral it is. The user is 
more than likely to pull out your I/O port and replace it with a 3Fax in mid operation. You select 
ASIC4 in the correct mode by sending a special control code. If there is an ASIC4 out there it will 
respond by sending back a non zero value. The peripherals ID can be read back from ASIC4's info 
register. This register also returns the state of the input lines INO, IN1, IN2. The coding example 
below shows how ASIC4 can be checked for, selected and the peripheral ID checked: 


HwNullFrame 

mov al, (SerialSelect or Asic4Id) ; First look for an 
SBUSY ; ASIC4 at the other 
SCONTOUT ; end of the link 
XNOP 


Revision 1.00 Page 58 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


SBUSY 
SDATAIN 
test al,al 
je NoAnASIC4IsItAnASIC5 
mov al, (SerialReadSingle or A4InfoR) ; Now see if we 
SBUSY ; have the right 
SCONTOUT ; peripheral 
XNOP 
SBUSY 
SDATAIN ; Mask out the unwanted 
and al,0Of0h ; bits 
cmp al,PERIPHERAL_ID ; check for correct ID 
jne IsASIC4ButNotRightPeripheral ; Got our peripheral 
ele ; Connection Okay! 
ret 
IsASIC4ButNotRightPeripheral: + Is an ASIC4 but not 
popt ; the right peripheral 
stc ; Connection Failed! 
ret 
NoAnASIC4IsItAnASIC5: ; No ASIC4 
mov al, (SerialSelect or Asic5NormallId) 
SBUSY ; Could have been an 
SCONTOUT ; ASIC5 so try to put 
XNOP stc ; back in the 
right mode 
ret ; Connection Failed 


Bits in ASIC4’s info register have the following definitions: 


Pot | Dmsb | DT Wiss | TN? TN NO 
Sending and Receiving data using ASIC4 


All ASIC4 peripherals are memory mapped into that ASIC's address space. To access a peripheral or 
a particular peripheral's register the ASIC must first be told to set its address bus to the appropriate 
location. Once it has been informed of the address which it is to access that location can be read from 
or written to as many times as required. The value to be written is held in the data register. To read 
or write to another location the address that the ASIC is accessing must be changed. To read from a 
random address within the ASIC's address space the sequence would be: 

1) Send a control code to inform the ASIC that it is to set its address bus to the following address. 

2) Send the address to position to. 

3) Send a control frame to inform the ASIC that we wish to read from this address. 

4) Read back the byte. 


To write a random value to and address within the ASIC's address space the sequence would be: 


1) Send a control code to inform the ASIC that it is to set its address bus to the following address. 
2) Send the address to position to. 

3) Send a control frame to inform the ASIC that we wish to write to this address. 

4) Send the byte. 


Overleaf are two 8086 assembler functions Input and Output which read from or write to an address 
within the ASIC's address space. These functions only give access to the bottom 256 addresses. For 
peripheral devices this is usually more than adequate. Interrupts should always be off during calls to 
these functions to prevent the S3/S3a/HC from multitasking. Note that in the following routines, 
A4Address and A4Data refer to the value of the respective ASIC4 registers. SerialWriteSingle has 
the value corresponding to a single frame write in the SIBO serial protocol format. These system 
defines can be found in the important include files ospack.inc and ossibo.inc. 


ProcBegin@ Output 


; 
; 

; Output byte to ASIC4-based peripheral 

; IN: DL holds the hardware address ASIC4 is to write to 


Revision 1.00 Page 59 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


; AL holds the byte to be output to that address 

push ax 

mov al, (SerialWriteSingle or A4Address) ;CTRL=Write to A4 address 
reg 

SBUSY 

SCONTOUT ;Send this control 
frame 

mov al,dl ;DATA=Hardware address 

SBUSY 

SDATAOUT ;Send this data 
frame 

mov al, (SerialWriteSingle or A4Data) ;CTRL=Writing data 
now 

SBUSY 

SCONTOUT ;Send this control 
frame 

pop ax ;DATA=Data to write 

SBUSY 

SDATAOUT ;Send this data 
frame 

ret 


ProcEnd noret 


ProcBegin@ Input 


; Input byte from ASIC4-based peripheral 
7 IN: DL holds the hardware address ASIC4 is to read from 
; OUT:AL holds the value read from that address 

mov al, (SerialWriteSingle or A4Address) ;CTRL=Write to A4 address 
reg 

SBUSY 

SCONTOUT ;Send this control 
frame 

mov al,dl ;DATA=Hardware address 

SBUSY 

SDATAOUT ;Send this data 
frame 

mov al, (SerialReadSingle or A4Data) ;CTRL=Reading data 
now 

SBUSY 

SCONTOUT ;Send above 
control frame 

SBUSY 

XNOP 

SDATAIN ;Receive data frame 

ret ;AL holds the data 


ProcEnd noret 


Obtaining and using a channel 


The s3/S3a/HC have three Psion serial links. Only one of these channels can be selected for 
communication at any one time. Two of these channels form the SSD slots. The third forms the 
expansion port. Before a device driver is able to talk to a peripheral it must both own and have this 
third channel selected. Many device drivers can exist in memory and more than one may access the 
peripheral. To prevent multiple access to a single peripheral a device driver must first own a serial 
channel before it is free to communicate to the ASIC4/S peripheral at the end of it. To check if a 
channel is free and then reserve it call the operating system function HwGetChannel. This will return 
with carry clear if the attempt to capture the channel was successful, carry set otherwise. 


mov al, InterruptMaskForDesiredChannel 
HwGetChannel 
jc CouldntGetTheChannel 


Obtaining the desired channel will usually be performed by a device drivers open vector. Open 
should fail if the channel is unavailable. If a device drivers takes possession of a channel it is its duty 


Revision 1.00 Page 60 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


to free it again once it is finished. This would normally be done when the device drivers is closed and 
is performed by the operating system function HwFreeChannel. 


mov al, InterruptMaskForDesiredChannel 
HwF reeChannel 


As illustrated in the above table, on a series 3a the interrupt mask for the expansion port (Port C) is 
defined by A9MSlave, on a series 3 Asic2Int. Interrupts are IRQ2 and IRQ4 respectively. Only one 
serial link can ever be selected at one moment in time. Selecting a particular channel means that you 
are unable to speak to another without selecting it instead. To select a channel the operating system 
call HwSelectChannel is used. 


mov al, SelectForDesiredChannel 
HwSelectChannel 
push ax 


HwSelectChannel will return in al the channel that was previously selected. Device drivers should 
select the correct channel on entry to any vector or interrupt service routine that needs to 
communicate down that channel. On exit the previously selected channel should be restored. 
Between the time when the channel is first selected and when the old channel is restored multitasking 
should be disabled. this will usually mean switching off interrupts. Because of the watchdog timer, 
interrupts cannot be left off for an indeterminate length of time. Communications down channels 
therefore will usually be restricted to short bursts. For the expansion port the channel to select on an 
S3a is defined by Select Channel5 on an $3 SelectChannel7. 


pushf 

eli 

mov al, SelectChannel5 
hwSelectChannel 

push ax 

mov dl, AddressOfInputBuffer 
call Input 

mov dl, AddressOfOutputBuffer 


call Output 


pop ax 
hwSelectChannel 
popf 


Controlling ASIC5's UART 


Before data can be sent or received from ASIC5's UART continuous clocking from the host must be 
enabled and a baud rate selected. The UART must be enabled by setting bit 0 in the port B mode 
register. The selected baud rate value is related to the result of dividing the required baud rate into 
the input clock frequency from the host of 1.536 MHz. The value generated from the equation given 
below forms a sixteen bit word. ASICS has two registers for selecting the baud rate. Register 10 
should contain the least significant byte and register 11 the most significant byte of the calculated 
word value. The table below lists the divisor values for some of the more commonly required baud 
rates: 


Divisor = 1-(96000/Desired Baud Rate) 


9600 a ee ae ee 
7200 fff 
4800 


Revision 1.00 Page 61 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The format of data communicated, stop bits, data bits, parity checking, is controlled by writing to the 
UART status/control Register. Bits in the UART status/control register have the following meanings: 


| 0 | Stateof the CTS line (PAI) ___| Generate break character 
iar 


A character to be transmitted should be written to the Transmitter Holding Register where ASICS will 
convert it to serial form for transmission. The register will be emptied once the character has been 
transmitted. ASIC5 contains no internal buffering. The Transmitter Holding Register must be empty 
before writing a character to it. The state of the Transmitter Holding Register is reflected in the 
Transmitter Empty bit in the UART status register. Enabling the Transmitting Holding Register 
interrupt will cause ASICS to generate an interrupt every time that the Transmitting Holding Register 
becomes empty. Reading the UART Status Register will clear the interrupt. Received characters are 
copied into the Receive Character Register. If the Receive Character Interrupt is enabled ASICS 
generates an interrupt on each character received. If the character is received in error due either 
parity, framing or overrun errors, appropriate bits in the UART Status Register are set to reflect this. 


Hold and Resumes 


There are three types of hold and resume. The first occurs when memory is being moved. An LDDs 
hold and resume vectors will always be called when this occurs. The second is a On/Off Hold and 
resume. An LDD will always be held and resumed when this occurs although it is not guaranteed that 
power will have been restored to the expansion ports when the resume is issued. The third type 
occurs when one of the pack doors is opened or a peripheral inserted. Only certain internal LDDs 
receive a Hold and Resume under these circumstances. Any loaded LDD will definitely not receive a 
Hold or Resume. To get around these problem, the TcK: device driver is used to provide a regular 
call to a routine within your driver. This call monitors the power to the expansion port and issues its 
own holds and resumes as appropriate. Holds and resumes can become nested and the whole situation 
can become rather complicated. The correct procedure for dealing with holds and resumes for an 
ASIC4 peripheral device driver (LDD) is given below. 


When a hold is received through the normal route the channel is marked as being under a normal 
hold. If the polling routine sees that the power has vanished and the channel is not already under a 


Revision 1.00 Page 62 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


normal hold then it holds the channel and marks it as being under a special hold. If a normal resume 
is issued channel can be resumed but only if power is present. If power is not present then the 
channel is marked as being under a special hold and the resume is put off. If the polling routine sees 
that the power is present and that the channel is under a special hold then it should resume the 
channel. 


Alternatively of course each time you read and write to your peripheral you could do a quick pre- 
check to see if the hardware is available and set-up correctly. This would dispense with the need to 
handle power up/down or pack door holds and resumes. You would still have to start and stop 
interrupts though when appropriate. 


Example Device Drivers 


An example device driver which will control the ASIC4 Example Interface Board described earlier 
can be found in the file A4EXIF.ASM. The device driver is a fully comprehensive multi-channel 
implementation. It supports all the mandatory logical device driver functions. Open will fail if the 
Interface Board hardware is not present. It has an interrupt service routine and handles Holds and 
Resumes correctly in all the distinct cases outlined earlier. In addition, asynchronous reads of the 
LED status are possible so a special routine to handle this case, the Wait Handler, is included. The 
driver has been made as fully comprehensive as possible both in terms of functionality and the choice 
of host machine. To this end, the code given can be compiled for the entire range of Psion machines 
simply by changing the appropriate machine Build Flag at the head of the file which then causes the 
correct interrupt masks to be selected for the machine. Chapter 11 of this document details the 
structure of A4EXIF.LDD a logical device driver constructed for the ASIC4 Example Interface Board. 


Chapter 12 details the functionality of a physical device driver for the ASIC5-based Psion 3-link 
peripheral that enables the host hardware to communicate with a PC by converting SIBO serial 
protocol signals into RS232 signals. Once again, this driver contains various build flags to facilitate 
conditional compilation. Common interrupt routine code is included and the LDD-PDD interface is 
specified. 


The source code for both A4ZEXIF.LDD and SYS$AS5.PDD is presented in the appendix to this 
document. 


Revision 1.00 Page 63 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


11. AN EXAMPLE DEVICE DRIVER FOR ASIC4: 
A4EXIF.LDD 


Introduction 


In this chapter, the functionality and code structure an example installable logical device driver, 
A4EXIF.LDD, is presented in some depth. Circuit details of the corresponding Psion peripheral for 
this driver, the ASIC4 Example Interface board, were outlined in chapter 8. A4EXIF.LDD enables 
software written using the Psion SDK to communicate with the prototype ASIC4 Example Interface 
board through means of standard PLIB calls such as ‘p_open' and 'p_write’. The description of 
A4EXIF.LDD is intended to provide a clear insight into the generalised structure of logical device 
drivers for peripherals based around the SIBO architecture. To this end the actual usefulness of the 
combined hardware-driver interface is of secondary importance. As shown earlier, the ASIC4 
Interface Board translates SIBO serial protocol signals into a parallel 8-way data bus format which 
can be used to set various 74HC series latches and gates. An eight-bit buffer and latch are commoned 
to eight LEDs. The latch is write-only and is used for setting the state of the LEDs. The buffer is 
read-only and is used to sense the state of the LEDs. In addition, a facility for generating hardware 
interrupts is provided by means of a suitably connected switch and third 8-way buffer (the status 
buffer). Address decoding is provided by two 2-to-4 decoders attached to address lines AO and Al. 


Code Structure 


Loading A4EXIF.LDD and Device Names 


A4EXIF.LDD is loaded into the RAM of the host machine by means of the following PLIB call in the 
application code: 


p_loadldd ("A4EXIF.LDD") ; 


The name of a device driver is the mechanism by which an application can obtain a channel to that 
device driver. LDDs all have three character names which are stored in the second field of the 
driver's LibEnt structure followed by a colon. This name is required to uniquely identify the LDD to 
the OS when attempting to open a channel on it. The A4EXIF LDD has the three character name 
"LED" so a channel with its handle in pcb may be obtained on it by means of the following call: 


p_open (&pcb, "LED:",-1); 


EPOC used the driver name in the p_open call to invoke the ToOpen system service which in turn 
invokes the Open vector on the associated device driver. 


The Single Code Segment and Data Storage 


As indicated earlier, loadable Psion device drivers have a single code segment and no data segment. 
Data associated with the driver is stored in one of two distinct ways dependent on its nature. Global 
data associated with the driver is stored in its code segment. Examples of such data are the channel 
interrupt masks and numbers have to be visible to all processes that may be using A4EXIF.LDD. 
Data local to the application invoking the driver, however, is stored in the heap space of that 
application. An example in A4EXIF.LDD would be the pointers to the open channel strategy vector 
parameters. 

The overall structure of the code segment is typical of Psion logical device drivers. The code segment 
begins with a CodeSeg directive followed by the LibEnt structure which defines the mandatory device 
driver functions as well as two non-mandatory ones. These are the Wait Handler and the replacement 


Revision 1.00 Page 64 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Tick Interrupt Vector. Before entering the code for these functions, all global variables are declared 
in what is termed the device driver's internal data space. Following the code for the Lib Ent functions 
comes the code for all the local driver functions. After these are the EndCodeSeg and end A4ExifLDD 
directives. 


Channel Status Ent and Open Channel Control Block 


At the head of the driver's assembler source file A4EXIF.ASM, various constants, compiler defines 
and type definitions are listed. It is here that templates are declared for the global structures that hold 
the key driver variables. In view of the above discussion, most device drivers employ at least one 
globally defined structure to hold the various important flags and masks that relate to the status of 
each separate channel on that driver. In the case of A4EXIF.LDD, two different structure types are 
employed, namely A4ExifStatusEnt and A4ExifEnt. The former is referred to in this chapter as the 
StatusEnt struc and is instantiated later on in the device driver code segment with each separate 
permissible channel of the main Psion host machines being assigned its own StatusEnt struc. A 
channel's StatusEnt struc is generally accessed through CS:DI and holds important channel-related 
information such as the A4ExifChannelOpen and A4ExifChannelRunning flags and the channel 
interrupt masks and interrupt numbers. The StatusEnt structure resides in the driver code segment 
whereas the A4ExifEnt struc is held in the heap space of the application invoking the driver and so is 
accessed through DS:BX. The A4ExifEnt structure contains a number of variables that are logically 
associated with a successfully opened channel and as such should be distinguished from the StatusEnt 
variables. An A4ExifEnt struc instantiated by invoking the device driver's open vector is referred to 
as the open channel control block and it is generally accessed through DS:BX. 


The layout of both the StatusEnt struc and the A4ExifEnt open channel control block struc are 
presented later in this chapter along with various other important pre-defined structs that were used in 
the construction of A4EXIF.LDD. Both of these structures were extensively used in the coding of the 
LDD functions described in the following pages. 


SIBO hardware and conditional compilation 


The number of expansion channels supported by a host SIBO machine is dependent on the hardware. 
In the case of the S3a, only one SIBO channel can legitimately be opened corresponding to expansion 
port A. With the HC and Workabout, it is possible to open up to three separate SIBO channels on 
ports A through to C. In A4EXIF.LDD, a global constant numberofchannels 1s set at the start of the 
device driver code segment to indicate the number of serial SIBO channels supported by the different 
machines. This will vary according to the Psion hardware present and in order to aid conditional 
compilation of the A4EXIF driver for the different host machine possibilities, a number of build flags 
can be used to set various constants within the include files. The hardware options with regard to 
these flags were outlined in the previous chapter. 


It should be noted that Psion device drivers should be designed to be easily adapted from machine to 
machine. With the A4EXIF driver, for instance, the only change that needs to be made in adapting it 
for use on another Psion machine is the alteration of the build flag at the start of the code segment. 
This flag indicates to the compiler which SIBO machine flags as well as other variables should be set. 
The SIBO machine flags are in turn used later in the code segment header to set the global 
numberofchannels variable mentioned above. For example, in A4EXIF.LDD, we have the 
following: 


if Corporate or Workabout 
numberofchannels equ 3 
else 


endif 


This type of code is used extensively in the conditional instantiation of A4ExifStatusEnts in the 
device driver's internal data space. Here different interrupt masks and SIBO channels are invoked for 
the different machines according to the host controller ASIC. For instance, in the case of a consumer 
(S3a), the hardware interrupt mask corresponding to expansion port C on an ASIC9 is mask 
A9MsSlave and the interrupt number is HwIrq2Revector. On an Workabout, the masks for expansion 


Revision 1.00 Page 65 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


ports A, B and C are A9MExpIntA, A9MExpIntB and A9MSlave respectively. The corresponding 
interrupt numbers are HwIrq4Revector, HwIrq5Revector and HwIrq2Revector. This conditional 
compilation code in A4EXIF.LDD outlined here is worthy of some study because it encapsulates all 
the information regarding masks and SIBO hardware channels required by the prospective developer 
interested in constructing a multi-platform Psion peripheral and driver. 


Mandatory LDD Functions 


The eight mandatory LDD functions are the Install, Remove, Hold, Resume, Reset, Units, Open and 
Strategy and they are all discussed in the context of the example device driver A4EXIF.LDD below. 


A4Exifinstall 
IN: No values are passed to the install vector. 
OUT: If successful return with carry clear. 
If installation unsuccessful, return with the carry flag set and error number in the 
AL register. 


PRESERVE: SS, SP and BP 


The install vector is called by the operating system when the device driver is loaded in order to 
initialise any internal variables. It should not be called directly by an application process but invoked 
indirectly by a 'p_loadldd("A4EXIF.LDD")' call. Typically at this stage the various open channel 
flags would be initialised to zero but in the case of the A4EXIF.LDD, this has already been done in 
the appropriate A4ExifStatusEnt struc headers. As a result, the install vector merely clears the carry 
flag and returns. 


A4ExifRemove 
IN: No values are passed to the remove vector 
OUT: If successful return with carry clear. 


If installation unsuccessful, return with carry set and error number in the AL 
register. 
PRESERVE: SS, SP and BP 


The remove vector is called by the operating system whenever the device driver is requested to be 
unloaded which is usually indirectly as the result of a call to 'p_devdel ("LED", E_LDD)'. ROM- 
resident drivers cannot be deleted so any attempt to invoke this vector on them will result in an error 
being returned. The code for the remove vector checks to see that all the device driver channels are 
closed and returns carry clear if this is the case. In the case of A4EXIF.LDD, a closed channel will 
hold a zero in its corresponding StatusEnt open channel flag. If any of the open channel flags is non- 
zero then the carry flag is set before returning indicating that an attempt has been made to unload a 
device driver that still holds at least one open channel. In the case of A4EXIF.LDD, the 
numberofchannels flag is used as a loop counter for the different hardware channel possibilities in a 
similar manner to the corresponding code in the open vector. 


A4ExifHold 

IN: AH register holds one of the following values: 
DevHoldNormal, DevHoldPowerDown Or DevHoldPowerFail 

OUT: None 


PRESERVE: SS, SP and BP 

The hold vector is called by the operating system whenever the device driver is requested to be held. 
This can occur as a result of three conditions which result in the three different possibilities for the 
value held in AH: 

1. Device memory segments about to be moved. AH holds DevHoldNormal. 


Revision 1.00 Page 66 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


2. Machine about to switch off due to power-save time-out or the off switch being pressed. AH holds 
DevHoldPowerDown. 

3. Machine about to switch off due to power source being removed or the batteries failing. AH holds 
DevHoldPowerFail. 

The hold vector code must be able to conduct a rapid shut down of the device driver because in the 
case of DevHoldPowerFail, the driver may only have a couple of ms before internal voltages fall to an 
unworkable level. The EPOC OS automatically handles the three cases highlighted above but in 
Series 3a machines and the Workabout, in addition to these there is another situation that requires the 
invocation of the hold vector, namely the opening/closing of the SSD pack doors on an S3a or 
Workabout. This is an action which can only be detected by means of software polling which requires 
the setting up of the ROM-resident "TcK:" device driver so that the door status can be checked each 
system tick (i.e. 32 times a second). The section on A4ExifTickInt provides a more detailed outline of 
the TCK interrupt code required to handle pack door opening and closing. It is this latter routine that 
polls for the open or closed status of the host machine doors, setting the global HoldFlag accordingly. 
The Hold vector code thus includes a check on the status of the HoldFlag and is generally optimised 
to be as efficient as possible. An outline of the structure of A4ExifHold presented below. It follows 
the pattern for a typical device driver: 


e Check the state of the global HoldFlag. 

e If the flag is non-zero, then the driver is already held and the function returns without taking 
any further action. 

e = If the HoldFlag is zero, then the function checks the status of all the channels that the driver 
is permitted to open. If any of these channels have their open channel flags cleared, it is not 
necessary to do anything as part of the process of holding the channel. Only in the case when 
the flags are set is the 'stopChannelRunning’ function invoked. As with the similar loop in 
the Reset vector, the global numberofchannels is used as the loop counter as each of the 
possible channels has to be checked. 


A4ExifResume 
IN: None 
OUT: None 


PRESERVE: SS, SP and BP 


The resume vector is called by the operating system to restart a held device driver. Resume will be 
called after a hold caused by any of the four possibilities indicated above in the section on A4ExifHold 
but it should be noted that in some cases, ASIC4 will only be switched on after the call to resume. 
The device driver is expected to recover from the previous hold and resume any suspended I/O except 
in the case of power failure where the resume vector ought to power up the peripheral and put it into a 
known state indicating to the user that data may have been lost. The resume vector will also have to 
handle the reinstallation of any interrupt service routines by checking the status of the open channel 
flag. 


e Check the state of the global HoldFlag. 

e If the flag is zero, then the driver has already resumed so return without further action. 

e If the flag is non-zero, then check the door status of the host machine with a call to the OS 
HwGetSsdData service. If the doors are open, then set HoldFlag to 2 to signal this position 
to the driver. If the doors are closed, then numberofchannels is used as a loop counter while 
the open channel flags of each of the permissible channels for the host hardware are checked. 
Only if these flags are set is the 'start TheChannelRunning’ function invoked. 


A4ExifReset 
IN: BX holds the device driver device handle 
CX holds user specified channel identification data. In this case, holds the address 
of the status struc identifying the open channel to be reset. 
OUT: None 


Revision 1.00 Page 67 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


PRESERVE: SS, SP and BP 


The reset vector enables a device driver to reset itself when the application which owns the device 
driver terminates abnormally before closing one or more open channels on that driver. The vector is 
only invoked by the operating system if it has been primed by means of a call to the ToRequestReset 
operating system service in the open vector. Such a call must be balanced by a corresponding call to 
IoRequestResetCancel in the close function code of the strategy vector. Registers BX and CX are 
required to be set up by the user prior to invocation of either of these services. BX should contain the 
device driver handle which is passed through DX in the open vector. CX should hold any suitable 
open channel identification data that can be accessed in the driver's internal data space (i.e. through 
CS:DI). In the case of A4EXIF.LDD, this information is the address of the channel StatusEnt 
structure. If a device driver is only capable of opening one channel, then it is irrelevant what CX 
holds. A reset should only be outstanding while some process has a channel open on the device 
driver. The format of A4ExifReset is similar to that of a typical reset vector and can be summarised 
as follows: 


e Move the address of the channel status Ent from CX into DI. 

e Check the value of the corresponding cs:[di].A4ExifChannelOpen flag. 

e If channel is not open to reset, then return from the vector otherwise call 
"StopTheChannelRunning’ and use HwFreeChannel to release the SIBO serial channel. Set 
the ChannelOpen flag to zero. 


A4ExifUnits 
IN: None 
OUT: AX holds the number of channels supported. 


PRESERVE: SS, SP and BP 


The A4ExifUnits function is called by the operating system when the device driver is requested to 
report the number of units (or channels) that it can support. This is primarily useful for purposes of 
information. 


A4ExifOpen 


IN: DX contains the device handle of the device driver 
SL is a pointer to an OpenEnt struc 
BP is a pointer to an IntEnt struc 
DS, ES point to the application process's data segment 
OUT: If successful return with carry clear and the address of the open channel in BX. 
i.e. BX holds the address of an A4ExifEnt struc which contains various fields of 
information concerning the open channel. 
If installation unsuccessful, return with carry set and error number in the AL 
register. 
PRESERVE: DS, ES, SS, SP, BP and DX 


The open vector is called by the operating system when a channel to the device driver is required to be 
opened. The device handle, which is passed through DX, is used by the operating system to route any 
I/O requests on the opened channel to the correct device driver. An LDD must place this handle in 
the ChanLibHandle field of the ChanEnt struc of the open channel structure allocated within the 
application's data segment. In the case of A4EXIF.LDD, this structure is the A4ExifEnt struc 
described in the Appendix to this document. The open vector of a device driver runs in the context of 
the process that has called p_open to open a serial port on that device driver. 


The OpenEnt struc consists of three fields , OpenNamePtr, OpenMode and OpenChan. The 
OpenNamefPtr points to the character immediately following the device name as passed in the 
p_open call. For instance, in the case of A4EXIF.LDD, the OpenNamePtr would point to the colon 
after LED in the name "LED:". The OpenMode field contains the mode for opening the device driver 


Revision 1.00 Page 68 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


which is not used in this example. The OpenChan field holds the I/O channel handle of the device 
that the driver is required to 'attach' to. Attached drivers add functionality to, or replace, a service 
provided by an underlying device driver. The IntEnt struc pointed to by BP can be used to reload the 
various segment registers if their contents have been altered. The A4ExifEnt struc requires further 
elaboration. It consists of four fields: A4Exiflo, A4ExifHandlerPtr, A4ExifStatusPtr and 
A4ExifA1Ptr. A4ExifHandlerPtr contains a handle to the driver's WaitHandler, A4ExifHandler. 
This is the routine required to handle the completion of asynchronous I/O requests and is described in 
more detail later on in this chapter. Of the remaining fields, A4ExifStatusPtr holds the location of the 
completion status word for I/O requests and A4ExifA1Ptr is a user-defined parameter. These two 
values are passed to the strategy vector through the RqEnt structure. A4Exiflo is itself a ChanEnt 
struc with sub fields ChanSignature, ChanNext and ChanLibHandle. After initialisation of this 
structure, [bx]. A4Exiflo.ChanSignature must hold 'TochanSignature’ and 
[bx].A4Exiflo.ChanLibHandle holds the handle to the device driver (stored in DX). Both of these 
values are again required by the strategy vector. The [bx].A4Exiflo.ChanNext field is used by 
attached drivers and is set to 0 for root drivers like A4EXIF.LDD. 


The code in an open vector follows a similar pattern in many LDDs and is presented in outline form 
below: 


e Determine the channel to be opened using the pointer to the device name held in 
[si]. OpenNamePtr. 

e If OK, disable interrupts and invoke the OS HwGet Channel call. 

e If OK, then set A4ExifChannelOpen flag to non-zero. 

e In order to poll for door-opening and closing, it is necessary to open a "TcK:" channel at this 
stage and initialise it by means of using the OS IowithWait service to call the TickInt vector 
on each system tick. 

e Re-enable interrupts and set up the calling process id using the ProcId service. 

e Check for the presence of the required hardware. If present return with carry clear. 

e Allocate space in calling process' heap (i.e. the application data space) to contain the I/O 
channel control block (an A4ExifEnt struc in the case of A4AEXIF.LDD) and set its base 
address to BX (thus BX holds the address of the open channel control block). 

e If OK, install the device driver Wait Handler using the IoAddHandler system service. A 
Wait Handler is required only if there are any asynchronous I/O requests to be handled. 

e If OK, initialise the fields inside the I/O channel control block that were outlined above. 

e Invoke IoRequestReset system service to handle unexpected termination of main program 
by invoking the driver's Reset vector. 

e Before leaving the Open vector, if the call succeeded, BX must hold the open channel control 


block handle. 
A4ExifStrategy 
IN: BX holds the allocated channel control block initialised in the open vector 


DX contains device handle of the device driver in the case of an LDD 

SL is pointer to RqEnt struc 

BP is pointer to IntEnt struc 

DS, ES point to data segment of application making the I/O function request 


OUT: If successful return with carry clear. Furthermore, in this case, if the strategy 
vector is meant to complete the I/O request (as is the case with IoClose for 
instance) then the completion status should be written back to RqStatusPtr location 
and the I/O semaphore signalled by calling IoSignal. If the I/O request is not completed 
by the strategy vector (as is the case with the asynchronous functions IoFuncRead 
and IoFuncWrite) then PendingErr should be written back to the location pointed to by 


RqStatusPtr and the I/O semaphore should not be signalled. 

If installation unsuccessful, return with carry set and error number in the AL 
register. 
PRESERVE: DS, ES, SS, SP and BP 


Revision 1.00 Page 69 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


When an application makes a I/O request on the opened device driver channel, the request is routed 
to this vector by the operating system. A device driver defines the set of strategy functions that it 
supports such as IoFuncSet, IoFuncSense, IoFuncWrite and IoFuncClose. The functions of a 
device driver are usually dependent on its purpose and there is no requirement to support any 
particular function. The ordering of these functions in the strategy vector table is defined in p_file.h 
and presented in A4EXIF.ASM. 


The SI register contains a pointer to an RqEnt struc which consists of four fields: RqFunction, 
RqStatusPtr, RgA1Ptr and RqA2Ptr. RqFunction contains the function number passed to the I/O 
request by the application. In the device driver strategy vector code, the value held in RqFunction is 
compared against the supported function numbers held in ToFuncClose, IoFuncRead etc. If the 
function number is not one of those supported then a call to IoRoot is necessary in the case of a root 
device driver such as A4EXIF.LDD. toRoot chains the I/O request through to the operating system 
which runs some default code to handle it. RqStatusPtr is a pointer to a memory location in the 
application data space which holds the value of the I/O request's completion status word. While a 
request is outstanding, this value is set to PendingErr and only when it completes does a completion 
code get written to this location. I/O requests can complete within the strategy vector or later after an 
interrupt. Often as is the case with A4EXIF.LDD, only a single request of any one kind can be 
outstanding at any time otherwise the application is panicked. RqA1Ptr and RqA2Ptr hold the values 
of two parameters that are passed to the IoAsynchronous EPOC service. Each synchronous strategy 
function has a similar pattern with explicit I/O being conducted whilst interrupts are disabled and a 
completed request being signalled with an OS ToSignal call prior to exit from the function. This call 
signals to the OS the completion of the particular I/O request entailed by the function call. The 
situation with regard to the one asynchronous strategy function is somewhat more complicated and is 
dealt with in greater detail in a later section. 


The structure of the strategy vector of A4EXIF.ASM is outlined below: 


e Determine the strategy function number using [si].RqFunction and compare with the below: 

e JIOFUNCREAD: Asynchronous read of latches U4 and U3. Panic if [bx].A4ExifStatusPtr != 
0. Update [bx].A4ExifA1Ptr and [bx].A4ExifStatusPtr with [si].RqA1Ptr and 
[si].RqStatusPtr respectively as the locations to be accessed on receipt of interrupt. Move 
PendingErr into the location pointed to by [bx].A4ExifStatusPtr to signal that the request is 
awaiting completion. Allow handler to be enabled through the IoEnableHandler OS call 
and exit without signalling completion of the request. 

e IOFUNCWRITE: Identical behaviour to that of IoFUNCSET which it calls. 

e TIOFUNCCANCEL: Used to cancel any pending asynchronous reads. This involves 
disabling the wait handler, consuming any stray signal from the interrupt routine by means of 
an OS IoWaitForSignal call and then storing cancelErr in the channel I/O request status 
word. 

e IOFUNCCLOSE: Close down the TCK channel and remove handler. Disable interrupts 
and HwFreeChannel setting A4ExifPid to 0 before re-enabling interrupts. Invoke 
IoRequestResetCancel system service and HeapFreeCell. Signal completion of I/O 
request by calling IoSignal system service. 

e IOFUNCSENSE: Reads the status and LED bytes from latches U4 and U3 respectively 
storing the results at the addresses pointed to by RgA1Ptr and RqA2Ptr. 

e IOFUNCSET: Sets latch U5 to contain the value pointed to by the sole argument in the 
call to P_FSENSE. 

e If not supported then call IoRoot system service. 


The Non-Mandatory LDD Functions 


The eight functions described above must be supported by all device driver. Typical Psion LDDs 
employ at least two other LDD functions. The first of these is a pseudo-interrupt routine which is 
invoked by the OS on each system tick. In A4EXIF.LDD, this function is represented by 
A4ExifTickInt and an outline of its purpose was presented earlier in the discussion on holding and 


Revision 1.00 Page 70 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


resuming device drivers. As was indicated then, the minimum functionality required by this routine 
is to poll the status of the host machine doors and if appropriate call the driver's Hold and Resume 
vectors. If in addition the LDD is intended to service any asynchronous I/O requests, a wait handler 
and common interrupt service routine are required. With A4EXIF.LDD, these two additional 
functions are represented by A4ExifHandler and ComInt respectively. The former function 
constitutes the second of the additional LDD functions as can be seen by examining the LibEnt 
structure for A4EXIF.LDD. The latter function is set up so that it replaces the default interrupt 
service routine code invoked by the OS on the receipt of hardware interrupts on the peripheral's SIBO 
channels. A4ExifHandler is invoked by the OS every time the I/O semaphore of the process that 
opened the channel is signalled with through an IoSignalByPidNoResched call indicating that an 
interrupt has been received and an outstanding I/O request has completed. The function of the wait 
handler is to deal with I/O semaphore signalling and to update the appropriate open channel control 
block field variables. The common interrupt service routine code in ComInt cannot do this because it 
is not permitted to access the application data space. This in turn is because the routine runs in the 
context of the process which was running when the interrupt occurred. A4ExifTickInt, the wait 
handler and the common interrupt service routine for A4EXIF.LDD as well further details as to how 
the latter two interact to handle asynchronous I/O requests are described below. 


A4ExifTicklint 


As was explained earlier in discussing the A4ExifHold vector, it is necessary to utilise the "TcK:" 
system tick device driver in order to handle the particular case of invoking a hold on A4EXIF.LDD 
when the host machine SSD pack doors are opened. Such an action automatically causes power to be 
removed from any peripherals. The TCK driver is opened via an OS Toopen call in the A4ExifOpen 
vector which returns with carry clear and a non-zero handle in AX if successful. In this case, the 
IoWithWait function is called to request an synchronous I/O service from the TCK driver. Prior to 
this call, the service number requested is held in AL and the I/O handle procured from the previous 
call to ToOpen is loaded into BX. The interrupt number of the tick poll routine, A4ExifTickInt, is 
loaded into CX so that as its parent driver is invoked on each system tick, the OS enters this vector. 
The reason the TickInt routine is required in A4EXIF.LDD is solely to handle the problem of 
recognising a sudden removal of power from the host machine. The OS has no way of testing for this 
condition other than polling its global 'Doorstatus' variable every system tick and taking the 
requisite course of action. As such, the outline of the code for the tick poll routine which is required 
in all Psion LDDs can be presented below. This outline should be carefully compared with the 
structure of the Hold and Resume vectors shown earlier in order to see how they interact: 


e Check the current status of doors which is held in SI. 
e¢ If DoorlsOpen then if global HoldFlag is zero, force a call to A4ExifHold, set HoldFlag to 2 
and return far 
else do a far ret 
e = Else if DoorIsClosed then 
if global HoldFlag is 2, force a call to A4ExifResume and return far 
else do a far ret 


It should be emphasised that A4ExifTickInt is only a pseudo interrupt service routine in that it does 
not preserve the status of the registers which is something that the device driver writer must 
undertake to ensure is done explicitly. 


The handling of synchronous and asynchronous I/O 


The provision of synchronous and asynchronous I/O services are an important aspect of writing any 
device driver. In the case of Psion drivers, all such services are the provided through the Strategy 
vector which is typically preceded by a Strategy Vector Table listing the complete set of I/O services 
that can be invoked on the driver. The strategy vector table for A4EXIF.LDD is presented below to 
provide an indication as to the kind of service routines that can be written: 


StrategyVectorTable label word 


Revision 1.00 Page 71 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


dw offset A4ExifDefault 7StrategyPanic 

dw offset A4ExifRead ;StrategyRead (function define is P_FREAD) 

dw offset A4ExifWrite ;StrategyWrite (function define is P_FWRITE) 
dw offset A4ExifClose ;StrategyClose (function define is P_FCLOSE) 
dw offset A4ExifCancel ;StrategyCancel (function define is P_FCANCEL) 

dw offset A4ExifDefault 7StrategyAttach 

dw offset A4ExifDefault 7 StrategyDetach 

dw offset A4ExifSet ;StrategySet (function define is P_FSET) 

dw offset A4ExifSense ;StrategySense (function define is P_FSENSE) 


Both synchronous and asynchronous I/O requests can be made on the driver through means of the 
PLIB 'p_iow (pcb, <func>, &A1, &A2)' call where pcb is the open channel handle, <func> is one of 
the above function defines and Al and A2 are two optional parameters required for the servicing of 
the request. The routing of an I/O request to the correct service code is done by the common code at 
the head of the strategy vector. Each time this vector is entered, BX holds the address of the open 
channel control block, DX the device handle of the device driver and SI a pointer to the strategy 
RqEnt struc used by the OS to follow the course of the I/O request. Using this information, it is 
possible to access all the relevant flags in the channel StatusEnt by moving [bx].A4ExifStatusEntPtr 
into DI. This leaves us with the open channel control block in DS:BX and the channel StatusEnt in 
CS:DI. 


Armed with the above information, it is possible to outline the general pattern of both synchronous 
and asynchronous I/O requests at an OS level. The case of synchronous requests is particularly 
straightforward since the servicing of the request can be completed entirely within the relevant 
strategy vector table function. It should be emphasised that in the outline presented below, disabling 
and re-enabling of interrupts only actually has to be done around any I/O. 


SYNCHRONOUS I/O REQUEST STRATEGY VECTOR TABLE FUNCTION 


pushf 
cli ;Disable interrupts 
< request service code > ;Relevant synchr. I/O processing 


ExitWithCompletionStatusZero: 
< set I/O request status word to zero > 


IoSignal ;Signals completion of I/O to OS 
XOr ax, ax 

onl ol ;Tells OS that strategy exited OK 
popf ;Re-enable interrupts 

ret 


ProcEnd noret 


Note that in the above outline, the single ToSignal call is made after completion of the I/O request in 
order to signal this fact to the OS. The situation is somewhat more complicated in the case of an 
asynchronous request because the I/O request strategy vector table function has to interact with both a 
wait handler function and an interrupt service routine. Of the I/O request services outlined above for 
A4EXIF.LDD, only one, namely A4ExifRead, is asynchronous and it serves as a good illustration of 
the nature of programming for asynchroneity. The steps taken in the A4ExifRead vector are outlined 
below: 


e = Set the ChannelReadCompleted flag to 0 (stored in cs:[di]. A4ExifChanReadCompleted) 
e If the address of the I/O request status word is non-zero then panic (i.e. there is an 
outstanding read request) 

e Update the open channel control block variables using the RqEnt struc 

e Load I/O request status word with PendingErr 

e Enable the wait handler by using the To—EnableHandler OS service 
The read request is now in a pending state waiting for completion via receipt of a hardware interrupt. 
When such an interrupt is received, the OS switches into the appropriately configured common 
interrupt routine ComInt. Here, the channelReadCompleted flag is set to indicate to the handler that 
the read request has completed. An IoSignalByPidNoReSched OS service call is also made to 
indicate to the OS that an as yet unspecified I/O request has terminated. This signal is consumed by 
the OS which means that at this stage, an IoSignal for completion of the original asynchronous 
request has yet to be made. The interrupt service routine exits after sensing the status and LED byte 
values from the ASIC4 Example Interface Board and loading the appropriate response bytes into the 
relevant locations in the device driver code segment. More details as to the functionality of the 
interrupt service routine are provided in the section on interrupts. The OS now invokes all the 
currently active wait handlers in order to determine which application is responsible for consuming 


Revision 1.00 Page 72 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


the completed read. The wait handler code includes the all-important IoSignal call that indicates to 
the OS that the original asynchronous read request has finally been accounted for. Receipt of this 
signal by the OS constitutes completion of the request. The outline code for the A4EXIF.LDD wait 
handler A4ExifHandler is outlined in the next section. 


A4ExifHandler 


A WaitHandler is a special function of the LDD which is nominated to be called by the operating 
system every time the I/O semaphore of the process that opened the channel is signalled. It will only 
actually be called if the application is already waiting for an outstanding I/O request to complete (1.e. 
while the application is hung in p_iowait). The handler function is the means by which hardware 
interrupts can be filtered through to the process which opened the I/O channel since it permits the 
rescheduling of processes. 


The WaitHandler is invoked in the open vector by using the IoAddHandler system service. When an 
application makes an I/O request, the I/O semaphore is signalled and the operating system calls the 
Wait Handler function while the application is waiting for the request to complete. The wait handler 
returns with CLC if no outstanding request has completed. Otherwise the wait handler returns with 
STC and zero in AL. The wait handler can include within it synchronous I/O requests to cancel or 
use up signals but it is not entered recursively (i.e. re-enterently) by the operating system. A wait 
handler is best viewed as a necessary requirement in dealing with the I/O semaphore signalling which 
cannot entirely be addressed in the appropriate interrupt service routine because the latter is not able 
to access the open channel's control block. 


Interrupts and Interrupt Service Routines 


The SIBO architecture allows for eight separate hardware interrupt sources. The EPOC operating 
system provides a GenSetRevector service to enable a device driver to install an interrupt service 
routine for any of these eight interrupt sources. When an interrupt occurs, the operating system 
preserves the state of all the registers before calling the appropriately-installed interrupt service 
routine. As a result of this, the interrupt service routine is free to employ any register it sees fit to use. 
A few important points ought to be made concerning the code within an interrupt service routine: 


e On an 8086 processor, interrupts cannot be nested so their is no requirement to disable 
interrupts whilst inside the interrupt service routine. 

e Interrupt service routines should operate as fast as possible. In general, operating system 
service routines are tuned to be of less than Ims duration. 

e Interrupt service routines run in the context of the process that was running at the time of the 
interrupt and should access only the device driver data space which, as with A4EXIF.LDD, 
typically resides in its own CS space. 

e Interrupt service routines should not cause a process rescheduling. To indicate that an event 
has occurred to the interrupted process, the ToSignalByPidNoResched system service 
should be called. If a call is made to this service, the interrupt service routine should exit 
with CLC otherwise it returns with STC. 


The interrupt routines called require knowledge as to the particular hardware SIBO channel being 
used by the driver at the time an interrupt occurs. This information is passed through to the 
GenSetRevector function in StartInterrupts by loading the address of the appropriate Int Vec routine 
from the A4ExifChannelIntVec field of the channel StatusEnt struc. As a result, when an interrupt 
occurs, the currently loaded IntVec routine is invoked. All the Intvec routines reload DI with the 
appropriate address of the channel StatusEnt in the device driver code segment before falling through 
to the common interrupt routine service code held in ComInt. 


Comint 


Revision 1.00 Page 73 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The common interrupt service routine code resides in the ComInt vector. The structure of this code is 
presented below. It should be emphasised that no data in the application data space and hence in the 
open channel control block can be accessed from ComInt. This explains why it is necessary for the 
OS to invoke a wait handler to clean up after the interrupt service routine code for a particular 
asynchronous I/O request has been run. 


e Check the value held in the chanReadCompleted flag 

e If this value is 2 then we do not have an asynchronous read completed but rather the 
interrupt line has been pulled low outside of an asynchronous I/O request. 

e If this value is 1 then we have an asynchronous I/O request completed and so 
IoSignalByPidNoResched must be invoked to signal to the OS that a read has completed. 

e In both cases, sense the status and LED bytes from the Example Interface hardware and load 
these values in the device driver's code segment A4ExifStatusEnt struc. 

e There are four possibilities of status byte corresponding to the four combinations offered by 
the two input switches, S1 and S2. These are used to output one of four separate LED bytes 
to the LEDs. 

e Awrite to AlNonSpecificEoi register (or A9BNonSpecificEoiW in the case of an ASIC9 
machine) must be done prior to exiting to let the OS know that the installed interrupt service 
routine has terminated. 


Other important local device driver functions 


The functions presented in this section are local to A4EXIF.LDD and perform various important tasks 
relating to the peripheral hardware such as groping the hardware and setting interrupts running. 
Since these tasks have to be undertaken by most device drivers, the relevant functions are outlined in 
greater detail. 


A4ExifCheckHardwarePresent 


Every Psion device driver has a characteristic 'CheckHardwarePresent’ or 'GropeHardware" function 
that usually involves checking for the presence of the required peripheral device by means of 
comparing a couple of ASIC4 identification bytes returned by the peripheral in response to a SIBO 
serial protocol identification message with the expected answers. The specific value of the InfoByte is 
unimportant as long asa "test al, al" call is made which will always return a non-zero answer if 
ASIC4 is present. In that case, the extended info byte should be tested for against what is expected 
from address lines A23-A27. 


Psion Workabout/HC machines have three physical serial links and two of these are accessed via the 
SSD slots. The third link corresponds to the serial expansion port. In order for a driver to talk to a 
peripheral connected to this port, it must specifically select this serial link. In order to prevent 
multiple access to a single peripheral, it is necessary in the first instance to check whether the serial 
channel is free or not. A call to the operating system function HwGet Channel with the appropriate 
interrupt mask in AL returns with CLC if the channel was captured successfully. Logically this call 
should be made in the Open vector but since it can only sensibly be made after the hardware has been 
successfully located it can be placed at the end of the GropeHardware function. A corresponding call 
to HwFreeChannel must be made when closing the channel. To actually select a channel prior to 
communication along it, a call to HwSelectChannel Is necessary. 


A4ExifStartChannelRunning 


This function is called at the end of the Open vector to set the ASIC4 Example Interface hardware 
running. It can also be invoked by the Hold vector. The function first checks the status of the global 
StatusEnt ChannelRunning flag. If this flag is clear, CheckHardware is called to determine whether 
the hardware is still connected and then StartInterrupts is called before the channelRunning flag is 


Revision 1.00 Page 74 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


set to indicate that the channel hardware has been started. The function returns with CLC on 
successful completion or with STC if no hardware was located. 


A4ExifStopChannelRunning 


This function simply clears the channelRunning flag if set and calls StopInterrupts unless the 
channel already has its ChannelRunning flag clear. The StopChannelRunning function will be called 
by Strategy vector when trying to close a channel and can also be called by the Resume vector. 


A4ExifStartinterrupts 


StartInterrupts is called whenever a call is made to StartChannelRunning. At the heart of the 
function is a call to the OS GenSetRevector function which is used to install a specified interrupt 
service routine in the place of the default routine held in the interrupt vector table. GenSetRevector 
is called with the interrupt vector number of the service to be replaced in AX and the offset and code 
segment of the replacement interrupt vector service in BX and CX respectively. BX is loaded from 
the ChannelIntVec field of the channel StatusEnt which holds the name of the specific interrupt 
service routine code (i.e. IntVecO, IntVec1 etc.). The latter functions set up the appropriate channel- 
specific variables before falling through to the common ComInt routine. The channel interrupt mask 
which is machine and channel dependent is written to the appropriate register on the host ASIC. In 
the case of ASIC9, this register will be A9BInterruptMaskRW. For ASIC1 it will be 
AlInterruptMask. 


A4ExifStopInterrupts 


StopInterrupts reinstalls the original interrupt service routine by invoking the GenResetRevector OS 
system service and signalling the interrupt mask to the corresponding host ASIC register. 


Structures and Include files 


Epocdef.inc and device driver strucs 


Epocdef.inc is an important header file that contains the definitions of various strucs extensively used 
in the construction of device drivers. It also contains the definitions of all the OS error values such as 
DeviceErr and NameErr that are used in A4EXIF.LDD to communicate an error to the application 
via AX. Listed below and overleaf are the key strucs defined in Epocdef.inc that were used in the 
coding of A4EXIF.LDD. 


LibEnt struc Start of device driver 
LibSignature dw ? 

LibInfo dw 2 

LibCount dw ? 

LibBase dw ? 

LibEnt ends 


OpenEnt struc Pointed to by SI in Open vector 
OpenNamePtr dw ? 

OpenMode dw ? 

OpenChan dw ? 

OpenEnt ends 

ChanEnt struc Used in open channel control block 
ChanSignature dw 2 

ChanNext dw ? 

ChanLibHandle dw ? 

ChanEnt ends 


IntEnt struc Pointed to by BP in Open and Strategy vectors 
IntFrame dw ? 

IntBP dw ? 

IntES dw 2 

IntDS dw ? 


Revision 1.00 Page 75 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


IntPC dw ? 
IntCs dw 2 
IntFLAGS dw ? 


IntEnt struc ends 


RqEnt struc Pointed to by SI in strategy vector 
RqFunction dw 2 
RqA1Ptr dw ? 
RqA2Ptr dw ? 
RqStatusPtr dw ? 


RqEnt struc ends 


A4EXIF channel strucs 


These are defined at the start of the A4EXIF.LDD code segment. The open channel control block is 
held in a structure of type A4ExifEnt and is allocated space from the heap of the process invoking the 
device driver's open vector. As such, it cannot be accessed from the Hold, Resume and Reset vectors 
or from the interrupt service routine, ComInt. The channel StatusEnt holds various key channel 
related flags. Each hardware channel has its own StatusEnt which is instantiated in a header in the 
device driver code segment following the LibEnt structure. This header block is usually held in 
CS:DI which is how the StatusEnt variables are accessed. The structure of both A4EXIF channel 
strucs is shown below: 


A4ExifEnt struc OPEN CHANNEL CONTROL BLOCK 
A4xifIo ChanEnt<> 

A4ExifHandlerPtr dw ? Pointer to the Wait Handler 
A4ExifStatus dw ? Address of I/O request status word 
A4ExifAlPtr dw ? Pointer to first argument 

A4ExifA2Ptr dw 2. Pointer to second argument 
A4ExifStatusEntPtr dw ? Pointer to channel's StatusEnt 
A4ExifTickHandle dw ? Handle to the TCK device channel 


A4ExifEnt ends 


A4ExifStatusEnt struc CHANNEL STATUS_ENT 

A4ExifChannelPid db ? Process id of process holding 
channel open 

A4ExifChannelOpen db 2 Is the channel open or not? 
A4ExifChannelRunning db ? Is the channel running? 
A4ExifChanReadCompleted db ? Flag used to indicate to handler 
when 

A4ExifChanneliIntMask db ? Contains the HW channel interrupt mask 
A4ExifChannelIntNum db ? Holds no. of interrupt vector to be 
replaced 

A4ExifChannelSelect db 2 SIBO channel select flag 
A4ExifChannelDummy db 2 Spare 

A4ExifChanneliIntVec dw ? Holds replacement int. vector routine 
name 


A4ExifStatusEnt ends 


Ossibo.inc and Ospack.inc 


Ossibo.inc is an important header file that contains the defines for all the ASIC2 and ASIC9 register 
addresses. Ospack.inc contains similar information but for ASIC4. 


Revision 1.00 Page 76 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


12. AN EXAMPLE DEVICE DRIVER FOR ASIC5: 
SYS$AS5.PDD 


Introduction 


In this chapter, the functionality and code structure an example installable physical device driver, 
SYS$AS5.PDD, is presented in some depth. Circuit details of the corresponding Psion peripheral for 
this driver, the Psion 3-link, were outlined in chapter 8. SYS$AS5.PDD enables software written 
using the Psion SDK to communicate with the 3-link peripheral through means of standard PLIB 
calls such as ‘p_open' and 'p_write'. This peripheral incorporates an ASICS as the SIBO serial 
protocol slave device. As explained earlier in chapter 7, ASICS has an on-board 16550 UART which 
means that it can be used in conjunction with the standard serial LDD provided an appropriate PDD 
is loaded. SYS$AS5 is a PDD intended for this purpose and its description in this chapter provides a 
clear insight into the generalised structure and construction of physical device drivers for peripherals 
based around the SIBO architecture. 


The LDD-PDD interface 


All Psion device drivers have a LibEnt structure at the head of their code segment which includes a 
vector table defining the functionality of the driver. In the case of SYS$AS5, four vectors are defined. 
These are: Install, Remove, Open and Strategy. The structure of the first three of these are fixed for 
most device drivers but the fourth can be specified in any way. This fourth vector defines the LDD- 
PDD interface and is constructed to allow the two drivers to best communicate with each other. In the 
case of serial PDDs, the approach taken is modelled on the LDD strategy vector with the 
corresponding strategy vector table and function numbers. This is a logical choice but it is important 
to emphasise that the LDD-PDD interface is completely user-definable and that the approach 
described in this chapter is optional. 


The key feature of any LDD-PDD interface is that the LDD must have no explicit concept of 
hardware. In the case of the serial LDD, for instance, it knows that it has a serial port that it can read 
data bytes from or write data bytes to but it is ignorant of the explicit implementation of the hardware 
at this port. That aspect is handled by the corresponding PDD which handles all the specifics of data 
byte I/O. In the case of an application writing a buffer to the serial port by means of a 
p_iow(P_FWRITE....) call, for instance, the LDD will first copy the data in the application's DS into 
a local CS buffer. It will then call the PDD to indicate that it intends to start sending data bytes when 
the PDD is ready to start receiving. When the PDD is ready to commence sending a byte out of the 
serial port, it calls a function (TransmitByte) in the LDD. This function reads the next byte to be 
transmitted from its local buffer and hands it to the PDD. The PDD duly transmits the byte and again 
calls TransmitByte until all the bytes are completed. The LDD then sends a special 'NothingToSend' 
signal to the PDD which indicates that transmission is finished. The LDD also sends an 
IoSignalByPidNoResched which causes its wait handler to be invoked by the OS. In this way, the 
IoSignal that signifies completion of the original write request is invoked by the LDD. Note that the 
LDD has no concept of interrupts, merely of sending a byte at a time and registering completion or 
otherwise of I/O requests. Futhermore, the PDD never takes the initiative from the LDD and merely 
undertakes one function at a time before returning control back to the LDD. The LDD-PDD interface 
is examined in greater depth later in this chapter when the structure of the PDD strategy vector is 
presented. 


Revision 1.00 Page 77 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Code Structure 


Device Names and Loading SYS$AS5.PDD 


SYS$AS5.PDD is loaded into the RAM of the host machine by means of the following PLIB call in 
the application code: 


p_loadldd("SYSS$AS5.PDD") ; 


The name of a device driver is the mechanism by which an application can obtain a channel to that 
device driver. LDDs all have three character names followed by a period, a further three characters 
and acolon. The first three characters of a PDD name are the name of the LDD to which the PDD 
belongs. The second set of three characters uniquely identify the PDD. The device name is required 
to uniquely identify the LDD to the OS when attempting to open a channel on it. The SYS$AS5 PDD 
belongs to the "TTY:" LDD. Its name as defined in its LibEnt structure is 'TTY.SR5'. Thus a 
channel with its handle in pcb may be obtained on it at the application level by means of the 
following call: 


p_open (&pcb, "TTY.SR5:A",-1); 


The qualifier after the colon indicates that the driver can support more than one channel. Channels 
are allocated a single character sequentially from the character 'A' up to the character 'C'. The 
number of channels that can be supported in this way is dependent upon the host hardware. Only one 
expansion port can be opened on the S3a for instance whereas three are possible on the Workabout 
and HC. EPOC uses the driver name in the p_open call to invoke the ToOpen system service which in 
turn invokes the Open vector on the associated device driver. 


The Single Code Segment and Data Storage 


All data associated with a physical device driver must be stored in its code segment. Examples of 
such data are the channel interrupt masks and numbers that have to be visible to all processes that 
may be using SYS$AS5.PDD. 


The overall structure of the code segment is typical of Psion physical device drivers. The segment 
begins with a CodeSeg directive followed by the LibEnt structure which defines all the device driver 
functions. Before entering the code for these functions, all global variables are declared in the 
internal (CS) data space. Following the code for the LibEnt functions comes the code for all the local 
driver functions, After these are the EndCodeSeg and end OsAs5PDD directives. 


The Channel struct and A5Ent struct 


At the head of the driver's assembler source file, SYS$AS5.ASM, various constants, compiler defines 
and types are listed. It is here that templates are declared for the global structures that hold the key 
driver variables. in the case of SYS$AS5, one main structure, the Sr5ChannelStruct, is employed to 
hold the various important flags and masks that relate to the status of each separate channel on the 
driver. This structure is termed the Channel struct and its fields are filled in during the course of 
running the PDD install and open vectors. Whenever the serial LDD invokes one of the PDD 
functions, the application must ensure that CS holds the address of the PDD's code segment which is 
where the Channel struc resides. The channel's Channel struct is usually accessed through DI or BX 
depending on preference. Its layout is presented later in this chapter along with other important 
defines that were used in the construction of SYS$AS5.PDD. 


SIBO hardware and conditional compilation 


As indicated previously, the number of expansion channels supported by a host Psion machine is 
dependent on the hardware. In the case of the S3a, only one SIBO channel can legitimately be 
opened corresponding to expansion port A. With the HC and the Workabout, it is possible to open up 
to three separate SIBO channels on ports A through to C. SYS$AS5.PDD is constructed to enable it 
to run on any host Psion platform. In its internal data space, the various hardware options for the 
SIBO channels, interrupt masks and interrupt numbers are coded in a large if statement thereby 


Revision 1.00 Page 78 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


permitting conditional compilation of the driver for the required host hardware. The only change that 
need be made in adapting it for use on another Psion machine is the alteration of the build flag at the 
start of the code segment. This flag indicates to the compiler which SIBO machine flags as well as 
other variables should be set. The conditional compilation table outlined here is worthy of some study 
because it encapsulates all the information regarding masks and SIBO hardware channels required by 
the prospective developer interested in constructing a multi-platform peripheral and accompanying 
PDD. 


The PDD Functions 


OsAS5install 
IN: Nothing 
OUT: If successful, return with carry clear 
If installation unsuccessful, return with the carry flag set and error number in the 
AL register 


PRESERVE: SS, SP, BP 


The install vector is called by the parent LDD whenever the PDD is required to be loaded. It cannot 
be called directly be an application only indirectly through the LDD in its Install vector. The install 
vector is called in the context of the OS with DS and ES in an unknown state. Memory will not be 
moved while in this function so the normal rules governing the use of ES and DS may be ignored. 


OsAS5Remove 


IN: Nothing 
OUT: If successful, return with carry clear 

If installation unsuccessful, return with the carry flag set and error number in the 
AL register 


PRESERVE: SS, SP, BP 


The remove vector is called by the parent LDD whenever the PDD is required to be unloaded. It 
cannot be called directly by an application and only indirectly through the LDD in its Remove vector. 
The remove vector is called in the context of the OS with DS and ES in an unknown state. Memory 
will not be moved while in this function so the normal rules governing the use of ES and DS may be 
ignored. 


OsAS5Open 
IN: SS:SI points to the OpenEnt structure 
ES, DS point to the DS of the application process. 
OUT: If successful, return with carry clear and control block in BX 
If installation unsuccessful, return with the carry flag set and error number in the 
AL register 


PRESERVE: SS, SP, BP 


The open vector is called by the parent LDD whenever a channel to the PDD is required to be opened. 
It cannot be called directly by an application and is typically invoked in the higher level LDD Open 
vector code by means of the DevOpenPpp OS system call. On invoking the open vector, SI points to 
the OpenEnt structure which contains three fields, namely OpenNamePtr, OpenMode and OpenChan. 
The OpenNamePtr points to the qualifier immediately following the device name in the call to 
p_open. In the case of SYS$ASS5, for instance, the OpenNamePtr would point to the 'a' in the name 
"TTY.SR5:A". This corresponds to an attempt to open the first hardware SIBO channel on the host 
machine which if successful will leave the address of the ChanO Sr5ChannelStruct in BX. The PDD 
open vector finally includes a call to the OS service HwGet Channel to obtain the requested SIBO 
channel. 


Revision 1.00 Page 79 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


The order of action undertaken by the parent serial LDD's open vector is generally fairly complicated 
and includes various calls to the PDD strategy vector routines. The situation is outlined overleaf: 


e Ensure that the LDD itself can be opened. 

e Call the PDD open vector using the OS DevOpenPDD OS call. 

e = If successful, call the OS service DevGet PDDAddress which returns the full segment:offset 
address of the PDD's fourth strategy vector in BX:AX. These values are loaded into the 
dword Channel struct field SerialPDDEntry. 

e Invoke the PDD strategy Open and SetHandlerCS functions to set up offsets and segments 
respectively to locations in the LDD above. 

e Invoke strategy Set to initialise the transmission baud rate. 

e Invoke strategy Start to set-up and then enable interrupts 


Once the DevGetPDDAddress service has been used to load the LDD's SerialPDDEntry field, it may 
be used to load in the address of any of the PDD's strategy functions. The DevGetPDDAddress OS 
call invoked in the LDD open vector must also be invoked in the LDD resume vector code since 
memory may have been moved while the LDD was held. The PDD is ignorant of such activity since 
the serial LDD is responsible for handling all holds and resumes. 


OsAS5Strategy 
IN: AX holds the vector number 
ES, DS point to the DS of the application process. 
OUT: If successful, return with carry clear and control block in BX 
If installation unsuccessful, return with the carry flag set and error number in the 
AL register 


PRESERVE: SS, SP, BP 


The strategy functions are invoked directly from the various serial LDD vectors to provide hardware- 
specific services. For instance, in order to set up the baud rate, it is necessary to invoke strategy Set. 
The strategy vector table for OsAS5Strategy is presented below and then the functionality of the 
important component vectors is outlined: 


AS5StrategyJumpTable label word 


dw offset AS5Open ;Load Handler offsets 

dw offset AS5Close ;Close the channel 

dw offset AS5Start ;Start the channel 

dw offset AS5Stop ;Stop the channel 

dw offset AS5Set ;Set the channel status 

dw offset AS5Sense ,;Return channel status 
dw offset AS5Control ;Drive the handshaking lines 
dw offset ASS5Enquire ;Returns baud rate 

dw offset AS5Enable ;Begin sending output 
dw offset ASS5SetHandlercCs ;Load Handler segments 


Open and SetHandlerCS go together and are invoked from the LDD open and resume vector code. 
Both are required to let the PDD know the address at which its LDD resides. The four full addresses 
passed through to Open and SetHandlerCS are of the LDD's control block and the LDD StatusInt, 
RecvInt and XmitInt vectors. Close is called in order to close an opened channel. Start and Stop are 
used to enable/disable interrupts and are invoked from the LDD open, hold/resume and set vectors. 
The order of action in the PDD Start vector is as follows: 
e Initialise PDD variables 
e Check H/W present 
e Start the hardware running. In the case of SYS$ASS5, part of this process involves starting a 
continuous clock from the host controller ASIC in order to trigger the UART clock on the 3- 
link's ASICS. In addition to this clock, the RTS and DTR lines must be driven low. 
e = Start interrupts. 
The common interrupt service routine code resides in the PDD ComInt function. This code is patched 
into the interrupt vector via the GenSetRevector system service. The interrupt mask contains bits to 


Revision 1.00 Page 80 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


generate the following interrupts: Receive character, Ready to send next character and Modem line 
change character. In SYS$ASS, all three interrupts are enabled in Start. It is important to realise 
that after masking in these bits, a Ready to send next character interrupt is almost immediately 
generated so the corresponding ComInt code must be able to handle this. 


CheckHardwarePresent 


This non-mandatory function is called from the Open vector and follows the lines of previously 
discussed CheckHardwarePresent code. After checking for an ASICS at the end of the serial link, the 
function returns with the carry flag clear if one is found. If a non-zero info byte is returned with an 
Asic5Normalld, then various other IDs are tried (Asic4Id, Asic8Id, Asic5PackId) before returning 
with the carry flag set. 


CheckHardwarePresentFromStart 


This is a non-mandatory function called only from the PDD Start vector. After checking that we have 
an ASICS at the end of the SIBO channel, the function sets the S_PERIPHERALMODE bit of the 
A5PortBMode register. This then puts ASICS into UART mode. 


Comint 


The common interrupt routine code is entered with DI holding the address of the appropriate channel 
struct. ASICS's control register (A5CtrlReg) is read first to determine which interrupt has occurred. 
The byte read from the register is compared against S_ MDINT (Modem lines interrupt), S_RXINT 
(Receive character interrupt) and S_TXINT (Transmit interrupt). The code to handle each of these 
cases is then entered prior to returning control back to the LDD via the Channel struct fields that were 
filled by a previous LDD calls to the PDD strategy Open and SetHandlersCS vectors. The LDD has 
no knowledge of interrupts and the purpose of ComInt is therefore to hide the hardware details of 
handling interrupts from the LDD. Once the interrupt has been serviced, a write is made to 
A9BNonSpecificEoiW in the case of ASIC9 or AlNonSpecificEoi for an ASIC1/ASIC2 based system 
to indicate to the OS that the interrupt has been serviced. 


Revision 1.00 Page 81 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


13. DEBUGGING AND TESTING DEVICE DRIVERS 


Introduction 


This chapter will detail the techniques that can be used by the developer to first debug and then test 
device drivers. The emphasis will be on the software methods such as: 
e¢ Good use of variables. e.g. Starting all the fields in the CS Channel Status structure with 
CS. 
e Debugging by eye. Even more important with regard to device drivers. 
e Using SDBG. The pitfalls and benefits. Working your way around the strategy vector calls 
with SDBG. 
e Construction of C test harness programs. Catching all the error flags that can be returned by 
device driver functions. 
e The comprehensive memory check program mem.c. 


Debugging Techniques 


A Psion device driver is written in 8086 assembler as an asm file and built using the Borland Turbo 
Assembler compiler. The subsequent debugging process centres around the construction of an 
appropriate PLIB test harness. The purpose of a test harness is to check a number of the device driver 
vectors to ensure that they do not return errors or cause panics. The majority of PLIB calls that would 
be used in this context return a negative integer that is used to ascertain the cause of the problem in 
the corresponding device driver vector. The code below, for instance, would be used to test the install, 
open, strategy close and remove vectors of the A4EXIF LDD: 


GLDEF_C VOID main(VOID) 
{ 

VOID *serH; 

INT ret; 


if ((ret=p_loadldd("A4EXIF.LDD") ) <0) 
{ 
p_printf ("Error %d on p_loadldd", ret); 
p_getch () 
p_exit (0) 
} 


else 
p_printf ("Successfully loaded A4EXIF.LDD"); 

if ((ret=p_open(&serH, "LED:",-1) ) <0) 
{ 
p_printf ("Error %d on p_open", ret); 
p_getch(); 


x 


else 


p_printf ("Successfully opened LED: channel"); 
p_close(serH) ; 
p_printf ("Successfully closed LED: channel"); 
} 

p_devdel ("LED",E_LDD) ; 

p_getch(); 

p_exit (0); 

} 


Revision 1.00 Page 82 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


If as often happens at this stage, a bug in the device driver causes the test harness program to crash, it 
is necessary to debug the driver code either by eye or using SDBG. Debugging by eye should always 
be the first resort, however, whenever the bug can be readily pinned down to a particular vector. 
Things to look out for include: 


e ~=An unbalanced stack: Check that the number of 'pushes' equals the number of 'pops' in the 
appropriate vector code. 

e Addressing the wrong location: Ensure that all the Channel status fields (stored in CS) are 
offset using the correct register and that that register holds the right value. The following 
code for instance requires DI to hold the address of the channel status struct prior to 


invocation: 
mov al, cs: [di].ChannelOpenFlag 


e Consistency: With regard to the last point, it is important to be consistent if possible and try 
and use the same register (i.e. DI) to hold the channel status structure. A different one 
(usually BX) should also be used to hold the address of the open channel control block. 

e Trashing BX and DI: If these registers are used in the vector code for anything other than 
addressing, check that their value is not being trashed by the operation. 


Debugging using SDBG is an extension of debugging by eye. The SIBO debugger allows the 
programmer to trace through the driver's source code instruction by instruction and observe the 
contents of the CPU registers in the process. In this way it is possible to discover any discrepancies in 
terms of the values stored in the various registers. Furthermore, tracing with SDBG will enable the 
user to pinpoint the source of panics. The first objective of the device driver debugging process 
should be to get the code outlined on the previous page to work OK. 


Further Testing Strategies 


Once installing, opening, closing and unloading are dealt with, a test harness can be expanded to 
include p_iow or p_ioc calls which map onto the LDD's strategy vector. At this stage, SDBG is 
particularly useful for testing purposes as breakpoints can be set and jumped to. In this way for any 
p_ioc(serH, <func>, &serStat, &Al,&A2) call, the contents of the status word, serStat, and the A1 
and a2 parameters can be tracked through the LDD's strategy vector. The value held by the status 
word at the end of a particular strategy call is the value returned by the corresponding PLIB 
p_iow/p_ioc call. Thus negative errors within the strategy code can be picked up by the test harness. 
A good test harness should be able to catch all the possible errors and at the least invoke p_printf to 
let the user know when one of them is returned. The file p_file.h contains a list of all the current 
return error values and the corresponding PLIB level error name. The entry for PendingErr, for 
instance is as follows: 


#define PendingErr (-46) 
#define E_FILE_PENDING PendingErr 


In order to induce the return of these error values it is necessary to extend the basic test harness 
outline to allow the user to undertake various pathological actions. For instance, the harness may 
include code that tries to open a channel twice which should result in InUseErr being invoked. By 
such means it is possible to ensure that a driver is not only operating as it should in normal 
circumstances but returning the correct error value when relevant. 


Memory Testing 


The final process that should be undertaken to fully test a device driver consists of the construction of 
an appropriate memory test harness. Three functions are presented on the next two pages which 
provide the core of such a comprehensive memory test program. The first function, CheckMemory, 
uses the PLIB routines p_allspce and p_sgfree to print out the current free bytes on the heap and the 
number of free segments in the host RAM. This function can be invoked after installing, opening, 
closing or removing a device driver to ensure that memory is not going to ‘alloc heaven’. The 
GobbleMemory function is first used to determine the amount of free memory available in segments 


Revision 1.00 Page 83 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


through calling p_sgfree. The PLIB p_sgcreate function is then invoked to create a new segment, 
"Test", that consists of all of this free memory. Finally, the p_sgcopyto PLIB function is called to fill 
"Test" with Ox55's. By using up all free memory in this way, it is possible to use segment "Test" to 
determine whether a particular driver vector is writing to the wrong location. TestGobble, presented 
overleaf, is the third function outlined. It uses the PLIB function p_sgcopyfr to check the values of 
the bytes in the segment "Test". If any of the 0x55's have been overwritten then we know that we 
have a problem. These three functions should be incorporated within the standard test harness 
functions already presented in this chapter. In this way, it is possible to generate a powerful generic 
test program that can be used as the basis for all device driver testing. 


LOCAL_C VOID CheckMemory (VOID) 
{ 

VOID *Heap; 

INT fbytes; 


fbytes=p_allspc (&Heap) ; 

p_printf ("Free Heap Memory =>%x bytes", fbytes) ; 
p_printf ("Free Segments =>%d",p_sgfree()); 
p_getch(); 

} 


[KR KR KK KR KK KI KK IK I I I I / 


LOCAL_C VOID GobbleMemory (VOID) 
{ 
UINT nParas, segSize; 
INT 3; 

LONG pos,i; 

UBYTE buf [256]; 


p_printf(" System RAM size = %d",p_getram()); 
p_printf ("Internal RAM usage = %d",p_sgramdisk())j; 
nParas=p_sgfree()j; 
p_printf ("Amount of free RAM = %d",nParas); 
segH=p_sgcreate("Test",nParas, E_SEGMENT_HIGH) ; 
if (segH) 

p_printf ("Created segment \"test\""); 


else 
{ 
p_printf ("Error in creating segment"); 
p_getch(); 
p_exit (0); 
} 
segSize=p_sgsize(segH) ; 
p_printf("Size of segment is %d",segSize); 
p_printf("In 16-byte paragraphs"); 
p_sleep(5L); 
for (j=0; j<16; j++) 
buf [j]=0x55; 


i=0; 
while (i<segSize) 
{ 
pos=i*16; 
if (p_sgcopyto(segH, pos, &buf [0],16) <0) 
{ 
p_printf ("Failed on p_sgcopy"); 
p_printf ("%d",i); 
p_getch(); 
} 
i++; 
} 
p_printf("Test segment full of 0x55s"); 
p_getch(); 
} 


[RRR KK KK KK KKK IK I I I I / 


Revision 1.00 Page 84 of 115 pages 


The Psion SIBO Hardware Development Kit 


LOCAL_C VOID TestGobble (VOID) 


UINT segCount; 
buf [16]; 


segCount=0; 
p_printf ("Checking segment integrity ..."); 
for (segCount=0; segCount<p_sgsize(segH); segCount+t+) 
{ 
if (p_sgcopyfr(segH, segCount*16, &buf [0] ,16) <0) 
p_printf ("Error in segment"); 


else 
{ 
for (i=0;i<16;i++) 
if (buf[i] !=0x55) 
{ 
p_printf ("OVERWRITE ERROR!"); 
p_printf ("Segment count=%d",segCount) ; 
p_printf ("Byte count=%d",i); 
} 
} 
} 
p_printf ("Test segment OK"); 
p_printf ("Heap integrity checks OK"); 
p_allchk (44); 
p_printf("If get here, heap OK"); 
p_getch(); 


} 


[KR KR KK KR KK KKK I I I I I  / 


Revision 1.00 


Psion PLC (c) May 1995 


Page 85 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


APPENDIX: SOURCE CODE FILES 


A4EXIF.ASM 


title A4EXIF -- Example ASIC4 Interface device driver 
subttl Copyright (c) Psion PLC (1994) 
name A4EXIF 
; 
; VER DATE BY DESCRIPTION 
jo -o-------------------------------------- 
7 1.00F 26/1/95 Mal Working Version 
BUILDSB=1 7S3a build environment (channels=1) 
S3c=0 ;Need to specify no s3c 
; BUILDSC=1 7S3c build environment (channels=3) 
; BUILDCH=1 ;HC build environment (channels=3) 
; BUILDHH=1 753 build environment (channels=1) 
include ..\inc\epoc.inc 
include ..\inc\epoclib.inc 
include ..\inc\epocsibo.inc 


include ossibo.inc 
include ospack.inc 


Example Logical Device Driver for prototype LED-ASIC4 Interface 
circuit for Corporate/S3C/Consumer serial port. 
Written by Mal Dec 1994/Jan 1995. 


Me oNe Ne 


A4EXIF CONSTANTS AND TYPES 


The following constants and type definitions 
are compiler directives used by the TCEP assembler 
when it is creating the LDD. 


Ne Ne Ne Ne Ne 


if Consumer 


numberofchannels equ 1 
else 
if Corporate or S3c 
numberofchannels equ 3 
else 
numberofchannels equ 2 
endif 
endif 


7;Channel StatusEnt block accessed through CS:DI 
A4ExifStatusEnt struc 


A4ExifCSProcessId dw <i ;Channel parent process id 
A4ExifCSChannelOpen db 2 ;Channel open flag 
A4ExifCSChannelRunning db ? ;Channel hardware running 
flag 
A4ExifCSChanReadCompleted db 2 ;Channel request completed 
flag 
A4ExifCSChannelIntMask db 2 ;Channel interrupt mask 
A4ExifCSChanneliIntNum db ? ;Channel interrupt number 
A4ExifCSChannelSelect db 2 ;SIBO Channel select 
A4ExifCSChanneliIntVec dw ? ;Channel int vector number 
A4ExifCSTickHandle dw ee ;TCK channel handle 
A4ExifCSA1Value db i ;Channel strategy Al parameter 
A4ExifCSA2Value db ? ;Channel strategy A2 parameter 


A4ExifStatusEnt ends 


;Open Channel Control block accessed through DS:BX 
A4ExifEnt struc 


A4ExifDSIo ChanEnt <> 7;Open channel control block Ent 
A4ExifDSHandlerPtr dw 2 ;Cant touch when under 
A4ExifDSStatusPtr dw ? ;Hold, Resume, Reset or 
A4ExifDSA1Ptr dw ? ;interrupt routine 
A4ExifDSA2Ptr dw es 
A4ExifDSStatusEntPtr dw ? 

A4ExifEnt ends 
A4PERIPH MASK equ Of0h 711110000b 


Revision 1.00 Page 86 of 115 pages 


The Psion SIBO Hardware Development Kit 


EXTENDED_INFO_BYTE equ 090h 
U5_ENABLE_ON equ 080h 
U5_ENABLE_OFF equ 000h 
;Latch addresses for reading/writing 
USOUTPUT_LATCH equ 00000000b 
U3INPUT_BUFFER equ 00000000b 
U4STATUS_BUFFER equ 00000001b 
cs: [di] .A4ExifCsAlValuefor 
INTERRUPT_LATCH equ 00000001b 
;Status byte masks 
S2S3_ON equ 00000011b 
S2S3_OFF equ 00000000b 
S2_ONLY equ 00000001b 
S3_ONLY equ 00000010b 
INTERRUPT_STATUS_MASK equ 00000011b 
7; LED bytes 
SOME_LEDS_ON equ 01010101b 
SOME_LEDS_OFF equ 10101010b 
TOP_LEDS_ON equ 11110000b 
BOTTOM_LEDS_ON equ 00001111b 
ZERO_BYTE equ 00h 
dgroup group stack 
assume ds:dgroup,es:dgroup,ss:dgroup 
CodeSeg 
7 A4EXIF ENTRY TABLE 
; Seseseo eee ee sececs 
ProcBegin@ A4ExifLDD 
; ssieceees 
dw LDDSignature 
db 'LED',0,0,0,0,0 
dw (VectorEnd-Vector) /2 
Vector: 
dw A4ExifInstall 
dw A4ExifRemove 
dw A4ExifHold 
dw A4ExifResume 
dw A4ExifReset 
dw A4ExifUnits 
dw A4ExifOpen 
dw A4ExifStrategy 
VectorHandler: 
dw A4ExifHandler 
if Asic9 
InterruptVectors: 
dw A4ExifTickInt 
endif 
VectorEnd: 
H A4EXIF INTERNAL DATA SPACE 
, 
; Device Driver global variables follow. 
; These variables reside in the code segment 
; and as such can always be accessed with 
7 the 'cs:' prefix. 


if Asic9 
if Consumer 


Channel0O A4ExifStatusEnt<0,0,0,0,mask 


Psion PLC (c) May 1995 


710010000b 
7;Sets LBO for latch U5 
;Deselects LBO for U5 


;Selects 
;Selects 
;Selects 


;Selects 


A9MSlave, HwIrq2Revector, SelectChannel5, IntVec0O,0,0> 


else 
if Corporate or S3c 


Channel0 A4ExifStatusEnt<0,0,0,0,mask 


AOMExpIntA, HwIrq4Revector, SelectChannel3, IntVec0O,0,0> 


Channell A4ExifStatusEnt<0,0,0,0,mask 


AQMExpIntB, HwIrq5Revector, SelectChannel4, IntVec1,0,0> 


Channel2 A4ExifStatusEnt<0,0,0,0,mask 


A9MSlave, HwIrq2Revector, SelectChannel5, IntVec2,0,0> 


Revision 1.00 


AO for writing 
AO for reading 


; reading 
Al for writing 


Page 87 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


else 
Channel0 A4ExifStatusEnt<0,0,0,0,mask 


AOMExpIntA, HwIrq4Revector, SelectChannel3, IntVec0O,0,0> 
Channell A4ExifStatusEnt<0,0,0,0,mask 


AQ9MExpIntB, HwIrq5Revector, SelectChannel4, IntVec1,0,0> 
endif 
endif 
else 
if Consumer 
Channel0O A4ExifStatusEnt<0,0,0,0,mask 


Asic2Int, HwIrq4Revector, SelectChannel7, IntVec0,0,0> 


else 
if Corporate 
ChannelO A4ExifStatusEnt<0,0,0,0,mask 
ExpIntLeftA, HwIrq3Revector, ExpChannelLeftA, IntVec0O,0,0> 
Channell A4ExifStatusEnt<0,0,0,0,mask 
ExpIntRightB, HwIrq2Revector, ExpChannelRightB, IntVecl1,0,0> 
Channel2 A4ExifStatusEnt<0,0,0,0,mask 
Asic2Int, HwIrq4Revector, SelectChannel7, IntVec2,0,0> 
else 
ChannelO A4ExifStatusEnt<0,0,0,0,mask 
ExpIntLeftA, HwIrq3Revector, ExpChannelLeftA, IntVec0O,0,0> 
Channell A4ExifStatusEnt<0,0,0,0,mask 
ExpIntRightB, HwIrq2Revector, ExpChannelRightB, IntVecl1,0,0> 
endif 
endif 
endif 
HoldFlag db 0 ;Hold/Resume flag 
SwitchStatus db ? ;Holds the masked status byte from U4 after 
interrupt 
ProcEnd noret 
ProcBegin@ A4ExifInstall, far 
; eee 
; Installs the device driver. 
7 Invoked after a PLIB 'p_loadldd("A4EXIF.LDD")' call to load the LDD 
; All of the fields inside the CS control blocks are preloaded 
; with the correct values at install time. Install therefore does 
; not do any work. 
7 IN: 
; Nothing 
7 OUT: 
; Carry Clear - driver successfully installed 
7 
cle ;The ChannelOpen fields are set to zero 
ret ;in the relevant ChannelStatusEnt headers 
ProcEnd noret 
ProcBegin@ A4ExifRemove, far 
; eSeseces eee 
; Removes the device driver. 
; Invoked after a PLIB 'p_devdel("LED",E_LDD) 'call to unload the 
H device driver. 
; A device driver cannot be removed if any of its channels 
i are still open. 
H IN: 
; Nothing 
H OUT: 
; Carry clear - successfully removed 
7 Carry set - remove failed, error number in AL 
7 
mov cx, numberofchannels ;Check that each 
mov di, offset Channel0O ;channel is closed 
xor ax, ax 
CheckAl1lChannelsClosedLoop: 
cmp cs: [di] .A4ExifCSChannelOpen, al ;Closed channels will 
jne WeHaveAChannelOpenSoFail ;have the value 0 in 
add di, (size A4ExifStatusEnt) ;their ChannelOpen 


Revision 1.00 Page 88 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


loop CheckAl1ChannelsClosedLoop ;flags 
jmp FinishedOkay 
WeHaveAChannelOpenSoFail: 
mov al, InUseErr ;Fail if not all 
stc ;closed 
ret 
FinishedOkay: 
cle 
ret 
ProcEnd noret 


ProcBegin@ A4ExifHold, far 


v 

; Called by the operating system whenever the device driver is 

; being moved or the machine is powering down. 

; This will also be called by our pack door polling function when 

; it sees that the doors have been opened and our peripheral has 

; lost power. 

; IN: 

7 Reason for the hold in AH 

7 OUT: 

7 Nothing 

13 
mov cx, 1 ;Hold can be called 
xchg cl, HoldFlag ;when the driver is 
cmp cl, 0 ;under a hold so 
jne AlreadyHeld ;re-entrancy blocking 

A4HoldFromTick: ;is required 
mov cx, numberofchannels 
mov di, offset Channel0 ; Loop because Hold 


HoldAllTheChannelsLoop: 


;must stop all the 


cmp cs: [di] .-A4ExifCSChannelOpen, ; channels 
je DontHoldBecauseNotOpen ;Is the channel open? 
push cx ;If it is then stop 
call StopTheChannelRunning yall interrupts 
pop cx 
DontHoldBecauseNotOpen: 
add di, (size A4ExifStatusEnt) 
loop HoldAl1lTheChannelsLoop 
AlreadyHeld: 
ret 


ProcEnd noret 


ProcBegin@ A4ExifResume, far 


3 Called by the operating system when it has finished moving the 
- device driver in memory or when the machine is switching back on. 
; Also called by our door polling routine when it sees that the doors 
; have been closed and we can resume communication with our peripheral. 
; IN: 
iH Nothing 
; OUT: 
7 Nothing 
is 
xor CX, cx ;Block in case of re-entrancy 
xchg cl, HoldFlag 
cmp cl, 0 
je AlreadyResumed 
if Asic9 
GenDataSegment ;Check to see if the pack 
HwGetSsdData ;doors are still closed 
mov bx, ax 
cmp es: [bx] .SsdDoorStatus, DoorOpen 
je DoorsAreOpen 
endif 
A4ResumeFromTick: 
mov cx, numberofchannels ; Loop because resume must 
mov di, offset Channel0 ;restart each open channel 
ResumeAllTheChannelsLoop: 
cmp cs: [di] .A4ExifCSChannelOpen, 0 ;Is the channel open? 
je DontResumeBecauseNotOpen 
push Cx 
call StartTheChannelRunning 
pop cx 
DontResumeBecauseNotOpen: 
add di, (size A4ExifStatusEnt) 
loop ResumeAl1lTheChannelsLoop 
AlreadyResumed: 


Revision 1.00 Page 89 of 115 pages 


The Psion SIBO Hardware Development Kit 


Psion PLC (c) May 1995 


ret 


DoorsAreOpen: 


mov HoldFlag, 2 
ret 
ProcEnd noret 


ProcBegin@ A4ExifReset, far 


Called when an application which opened a channel terminates without 
closing the device driver. 
A device driver, for each open channel, has to request that the 
operating system calls this function when the application 
terminates abnormally (ie without closing an open channel). 
Reset can supply one piece of identifying data which will be 
passed in CX. This would usually be the channel's number or CS 
control block pointer. 
Reset just needs to clear interrupts, hardware reservations, and free 
the channel. Any allocated space will be cleaned up for you by the OS. 
IN: 

The device driver's handle in BX 

The address of the status struc identifying the channel in CX 


7 OUT: 
; Nothing 
, 
mov di, cx 
cmp cs: [di] .A4ExifCSChannelOpen, 0 
je NotOpenToReset 
call StopTheChannelRunning 7Stop interrupts 
mov al, cs: [di] .A4ExifCSChannelIntMask ;Free the reserved 
HwF reeChannel ;hardware 
mov cs: [di] .A4ExifCSChannelOpen, 0 ;The channel is now 
NotOpenToReset: ;free 
ret 


ProcEnd noret 


ProcBegin@ A4ExifUnits, far 


Called to find how many open channels the driver will support 


- In: 
; Nothing 
- Out: 
H The total number of channels supported in AX 
, 
mov ax, numberofchannels 
ret 


~ 


ProcEnd noret 


ProcBegin@ A4ExifOpen, far 


Opens a device driver channel. 
Invoked after the PLIB call 'p_open(é&appHandle, "LED:*",-1)'to open a 
channel to the device driver. 


, 

, 

7 

H Tn: 

; OS device handle of the device driver in DX 

; Pointer to the OpenEnt struc in SI 

; Pointer to the IntEnt struc in BP 

; DS,ES,SS point to the applications data space 

i Out: 

; Carry clear - BX holds the address of the open channel 

7 Carry set - AL holds the error number 

is 
cld ;Interrupts off to 
pushf ;prevent multiple apps 
oli ;calling open 
mov si, [si] .OpenNamePtr ; Simultaneously 
mov al, [sitl] 
CharToFoldedChar ;Read the unit no. 
cmp al, 'A' ;part of device name 
jb OpenNameErr ;to find which channel 
sub al, 'A' ;to open. eg "LED:A" 
cmp al, numberofchannels 
jae OpenNameErr 
xor ah, ah 
push ax ;Map the channel no. 
mov dx, (size A4ExifStatusEnt) ;to a channel control 
mul dx ;block in our CS 
pop ax 7; space 


Revision 1.00 


Page 90 of 115 pages 


The Psion SIBO Hardware Development Kit 


mov di, ax 
add di, offset Channel0O 
cmp cs: [di] .A4ExifCSChannelOpen, 0 
je GetATickChannel 
popft 
mov ax, AlreadyOpenErr 
jmp ChannelAlreadyOpen 
GetATickChannel: 
mov cs: [di] .A4ExifCSChannelOpen, 1 
mov cs: [di] .-A4ExifCSChannelRunning, 0 
popft 
ife Asic9 
jmp GetHardwareChannel 
else 
push ax 
mov ax, ((':' shl 8)+'K') 
push ax 
mov ax, (('C' shl 8)+'T') 
push ax 
mov bx, sp 
ToOpen 
jne GotATickChannel 
add sp, 6 
mov ax, LockedErr 
jmp OpenFailed 
GotATickChannel: 
add sp, 6 
mov cs: [di] .A4ExifCSTickHandle, ax 
push ax 
mov bx, ax 
mov ax, IoFuncStart 
mov ex, 1 
push cx 
push cx 
push ax 
mov cx, (InterruptVectors-Vector) /2 
push cx 
mov cx, sp 
ToWithWait 
add sp, 8 
pop dx 
jmp GetHardwareChannel 
endif 
OpenNameErr: 
popft 
mov ax, NameErr 
jmp ChannelAlreadyOpen 
GetHardwareChannel: 
mov al, cs: [di] .A4ExifCSChannelIntMask 
HwGetChannel 
jne CheckHardwareNowThatSIBOChannellIsOpen 
mov ax, InUseErr 
jmp FreeTckAndExit 
FreeTckAndChannelHardware: 
mov al, cs: [di] .A4ExifCSChannelIntMask 
HwF reeChannel 
mov ax, DeviceErr 
FreeTckAndExit: 
if Asic9 
push ax 
mov bx, cs: [di] .A4ExifCSTickHandle 
IoClose 
pop ax 
endif 
OpenFailed: 
mov cs: [di] .A4ExifCSChannelOpen, 0 
ChannelAlreadyOpen: 
stc 
OpenExit: 
ret 
CheckHardwareNowThatSIBOChannellIsOpen: 
Proclid 
mov cs: [di].A4ExifCSProcessId, ax 
mov cs: [di] .A4ExifCSChanReadCompleted, 0 
call CheckHardwarePresent 
jc FreeTckAndChannelHardware 
mov cx, (size A4ExifEnt) 
HeapAllocateCell 
jc FreeTckAndChannelHardware 
mov bx, ax 


Revision 1.00 


Psion PLC (c) May 1995 


;Offset in DI 


;Check to see if 
;channel is already 
;open 


,Obtain a TCK channel so 
;we can poll the door state 


7;If HC, we don't need 
;to set up the TCK 
; routine 


;Try to open "TCK:" 
;channel with "TCK:" 
; string on stack 


;TCK will call our 
,door-polling function 
732 times a second 


7Start our 
,door-polling function 
;running by starting 
;the "TCK:" channel 


7Frequency 1 tick 
;Data irrelevant 
;Handle to driver 
;TCK function to call 


7;Check the hardware 
;is available then 
;reserve it 
;Returns with carry 
;clear if OK 


7Set up the calling 
;process ID 


;Returns with carry 
;clear if successful 
;Allocate a control 
;block in our app's 
;data space 


Page 91 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


push bx ;IloAddHandler trashes BX 
mov al, (VectorHandler-Vector) /2 ;Set up our wait handler 
ToAddHandler ;Leaves the address of 
pop bx ;handler in AX 
jne GotHandler 
push ax ;If no handler, open fails 
HeapFreeCell 
pop ax 
jmp FreeTckAndChannelHardware 
GotHandler: 
mov [bx] .A4ExifDSStatusEntPtr, di 
mov [bx] .A4ExifDSHandlerPtr, ax 
mov [bx] .A4ExifDSStatusPtr, 0 
mov [bx] .A4ExifDSIo.ChanNext, bx 
mov [bx] .A4ExifDSIo.ChanSignature, IoChanSignature 
mov [bx] .A4ExifDSIo.ChanLibHandle, dx 
mov cx, al ; loRequestReset takes 
xchg bx, dx ;the device handle in 
IoRequestReset 7BX and the channel 
xchg bx, dx ;handle in CX 
xor ax, ax 
call StartTheChannelRunning 
ReturnCLc: 
cle 
ret 
ProcEnd 
if Asic9 


ProcBegin@ A4ExifTickInt, far 


This function is called by the tick handler on every tick of 

; the system clock. This happens 32 times a second. 

; The operating system will call a device driver to hold when memory is 
; being moved and when the machine is being powered down. It will not 

; call the device driver when the pack doors are opened. 

Opening the pack doors will cause power to the peripheral to be cut, 


; 
; and therefore the driver needs to be held in the way it would be if 
; the machine powered down. Only for Asic9 based machines. 
; This function checks the state of the doors on every tick and calls 
iH Hold and resume when it sees the status of the doors change. 
H IN: 
; The state of the door in SI 
; OUT: 
; Nothing 
; 
cmp si, DoorOpen 7Is the door open 
je TheDoorIsOpen 7or closed? 
cmp HoldFlag, 2 7Closed Door, HoldFlag=2 
je NeedToDoTheResume ;means we do a resume 
ret 7Closed Door, HoldFlag!=2 
NeedToDoTheHold: 
mov HoldFlag, 2 
jmp A4HoldFromTick 
NeedToDoTheResume: 
mov HoldFlag, 0 
jmp A4ResumeFromTick 
TheDoorIsOpen: 
xor ax, ax 
cmp HoldFlag, al 
je NeedToDoTheHold 
ret 
ProcEnd noret 
endif 
ProcBegin@ A4ExifHandler, far 
; 
; When an application is waiting within an iowait and a signal is 
; generated then before passing that signal to the application the 
: OS first runs any wait handlers belonging to the device driver 
; channels that the application has open. 
; The interrupt routine can generate a signal but cannot fill in any 
; status words or pass values back to the application because the 
; applications DS space is not available. The handler can consume a 
; signal generated by an interrupt and then fill any status words 
7 before re-signalling the application. A handler always has access 
; to the application's DS space. The wait handler can consume the 
7 signal which is then no longer passed back to the application. 
Hi IN: 


Revision 1.00 Page 92 of 115 pages 


The Psion SIBO Hardware Development Kit 


Ne Ne Ne Ne 


Psion PLC (c) May 1995 


Pointer to our control block in applications DS space in BX 
DS,ES,SS point at application's data space 


OUT: 
Carry clear - do not consume the signal, signal not for us 
7 Carry set - consume the signal, re-enable handler if AL 
; non-zero else don't re-enable handler if AL=0. 
7 
cld 
pushf 
cli 
mov di, [bx].A4ExifDSStatusEntPtr ;Is the signal for us? 
cmp cs: [di] .A4ExifCSChanReadCompleted, 1 
jne ExitHandlerSignalNotForuUs ;If it is, copy 
mov cs: [di] .A4ExifCSChanReadCompleted, 0 ;the values read in 
mov al, cs: [di] .A4ExifCSA1Value ;the interrupt 
mov ah, cs: [di] .A4ExifCSA2Value ;routine back to 
mov di, [bx].A4ExifDSA1Ptr ;the application 
mov [di], al ;Asynchronous read 
mov di, [bx].A4ExifDSA2Ptr ;has been completed 
mov [di], ah 
xor di, di 
xchg [bx] .A4ExifDSStatusPtr, di ;Clear the status 
mov word ptr [di], 0 ;word 
popft 
ToSignal 
xor ax, ax 
stc ;STC and AL!=0 => 
ret ;consume signal and 
ExitHandlerSignalNotForus: ;don't re-enable 
popft ;handler 
elec 
ret 
ProcEnd 
StrategyVectorTable label word 
dw offset A4ExifDefault ;StrategyPanic 
dw offset A4ExifRead 7 StrategyRead ie P_FREAD 
dw offset A4ExifWrite ;StrategyWrite ie P_FWRITE 
dw offset A4ExifClose ;StrategyClose ie P_FCLOSE 
dw offset A4ExifCancel 7 StrategyCancel ie P_FCANCEL 
dw offset A4ExifDefault ;StrategyAttach 
dw offset A4ExifDefault ;StrategyDetach 
dw offset A4ExifSet ;StrategySet ie P_FSET 
dw offset A4ExifSense ;StrategySense ie P_FSENSE 
ProcBegin@ A4ExifStrategy, far 
Called by the operating system when an I/O request is made on 


the device driver. 

Calls to this funcion from an owning application will usually take 
the form p_ioc(pcb, func, &Stat, &Al, &A2) ; 

The strategy function is called with a function number specifying 
the action which the driver is to take, a status word to fill when 
the action is complete, and two arguments Al and A2. 


Nee Ne Ne 


Se ee 


All strategy functions must complete with a signal to the application. 
Functions can be asynchronous and need not complete immediately. 
IN: 
Pointer to our control block in the applications DS in BX 
7 Device driver handle in DX 
; Pointer to the RqEnt struct in SI 
; Pointer to a IntEnt struct in BP 
; DS,ES,SS point at the applications data space 
i OUT: 
; Returned value in AX 
; Must call IoSignal somewhere to signal completion 
; of the I/O request. 
v 
mov ax, [si].RqFunction ;Get the function number 
mov dx, [si].RqAlPtr ;DX holds the first argument 
mov di, [si].RqStatusPtr ;for convenience 
mov word ptr [di], PendingErr 7Status word holds 
shl ax, 1 ; E_FILE_PENDING 
mov di, ax 
push StrategyVectorTable[di] ;Jump to required function 
mov di, [bx] .A4ExifDSStatusEntPtr ;with our CS control block 
retn ;pointer in DI 
A4ExifDefault: 
ToRoot 


Revision 1.00 


Page 93 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


ret 
ExitWithCompletionStatusZero: 

xor ax, ax ;Common exit points 
ExitWithOtherCompletionStatus: 

mov di, [si].RqStatusPtr 

mov word ptr [di], ax 

ToSignal 
ExitStillPending: 

xOr ax, ax 

cle 

ret 


ProcEnd noret 


STRATEGY VECTOR TABLE FUNCTIONS 


IN: 
DX holds the pointer to the first argument in 'p_iow(...)' call 
BX holds the address of the open channel control block 
CS:DI holds the address of status struc identifying the open channel 


See eee Ty 


ProcBegin@ A4ExifRead, far 


H Strategy vector table function that handles asynchronous byte reads 
7 from the LEDs and switches. 

i; The corresponding PLIB call is p_ioc(pcb,P_FREAD, &Stat, &Argl, &Arg2) ; 
; The request is completed when the interrupt routine signals the 

; handler which in turn signals the application passing back the values 
; read at the time of the interrupt through the AlPtr and A2Ptr. 

H IN: 

; Pointer to control block in applications data space in BX 

i Pointer to control block in our CS space in DI 

; Al (pointer to Argl) in DX 

, 

v 


OUT: 
Jumps to common exit point 
. Panics if multiple requests 
, 
cmp [bx] .A4ExifDSStatusPtr, 0 ;Panic if we already 
jne PanicPending ;have an I/O read request 
pushf ;pending on the channel 
cli ;Disable interrupts 
mov cs: [di] .A4ExifCSChanReadCompleted, 2 
mov ax, [si].RqA1Ptr 
mov [bx] .A4ExifDSA1Ptr, ax ; Store the locations to 
mov ax, [si].RqA2Ptr ;put the data when we get it 
mov [bx] .A4ExifDSA2Ptr, ax 
mov di, [si].RqStatusPtr 
mov [bx] .A4ExifDSStatusPtr, di ;DI holds the address 
mov word ptr [di], PendingErr 7of status word and we 
popf ;Signal that we are waiting 
mov bx, [bx] .A4ExifDSHandlerPtr ;for completion of read 
mov cl, 
ToEnableHandler ;Enable Wait Handler 
jmp short ExitStillPending 7No IoSignal because 
PanicPending: ;we are still waiting 
mov al, PaniclIoPending 
ProcPanic 


ProcEnd noret 


ProcBegin@ A4ExifWrite, far 


This function sets the state of the LEDs. 

It completes immediately after setting the state as it has nothing 
to wait for. 

Write is the same as set. 


Ne Ne Ne Ne Ne te 


IN: 
; Pointer to control block in applications data space in BX 
; Pointer to control block in our CS space in DI 
. Al in DX 
- OUT: 
- Jumps to Set 
, 
jmp WriteAndSetAreTheSame 


ProcEnd noret 


ProcBegin@ A4ExifClose, far 


Revision 1.00 Page 94 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Handles the request to close a channel. 
called by the PLIB call p_iow(pcb,P_FCLOSE) or p_close (pcb) 


Ne Ne Ne Ne 


IN: 
Pointer to control block in applications data space in BX 
; Pointer to control block in our CS space in DI 
; OUT: 
; Jumps to common exit point 
, 
call StopTheChannelRunning 7Stop interrupts 
if Asic9 
push bx ;Close down the 
mov bx, cs: [di] .A4ExifCSTickHandle 7;"TCK:" channel 
IoClose 
pop bx 
endif 
push bx 
mov ax, [bx] .A4ExifDSIo.ChanLibHandle ;Remove the wait 
push ax ;handler 
mov bx, [bx] .A4ExifDSHandlerPtr 
IoRemoveHandler 
cmp cs: [di] .A4ExifCSChanReadCompleted, 0 ;If the interrupt 
je NoSignalToConsumeFromInterrupt ;has signalled the 
ToWaitForSignal ;handler we need to 
NoSignalToConsumeFromInterrupt: ;consume its signal 
pop bx ;now the handler 
mov cx, di ;has been removed 
ToRequestResetCancel 
pop bx 7No longer need reset 
HeapFreeCell ;Free our control 
mov al, cs: [di] .-A4ExifCSChannelIntMask ;block in app's DS 
HwFreeChannel 
mov cs: [di] .A4ExifCSChannelOpen, 0 
jmp ExitWithCompletionStatusZero 7To signal completion 
ProcEnd noret 7,of close request 
ProcBegin@ A4ExifCancel, far 
v 
; Cancel any pending asynchronous read. 
; Called by the PLIB function p_iow(pcb,P_FCANCEL) ; 
i In: 
; Pointer to control block in applications data space in BX 
; Pointer to control block in our CS space in DI 
; Out: 
; Jumps to common exit point 
7 
pushf 
cli 
cmp [bx] .A4ExifDSStatusPtr, 0 ;Check that there is 
je NothingToCancel ya request pending 
push bx 
mov bx, [bx] .A4ExifDSHandlerPtr 
sub cl ol 
ToEnableHandler ;Disable Wait Handler 
pop bx 
cmp cs: [di] .A4ExifCSChanReadCompleted, 1 
jne NoSignalFromInterrupt ;TO consume any stray 
ToWaitForSignal ;Signal from the 
NoSignalFromInterrupt: ;interrupt routine 
mov cs: [di] .A4ExifCSChanReadCompleted, 0 
xor fomcramre be ;To signal completion 
xchg di, [bx].A4ExifDSStatusPtr ;of the outstanding 
mov word ptr [di], CancelErr pasync read request 
ToSignal ;Signal to p_waitstat 
NothingToCancel: 
popft 
jmp ExitWithCompletionStatusZero 7To signal completion 
ProcEnd noret 7of the cancel request 
ProcBegin@ A4ExifSet, far 
, 
7 Write a value to the LED latch. 
; Can be called by the PLIB call p_iow(pcb,P_FSET, &Argl); where Al 
; is an unsigned byte. 
; Write is the same as set. 
7 IN: 
; Pointer to control block in applications data space in BX 
7 Pointer to control block in our CS space in DI 
7 Al (pointer to Argl) in DX 


Revision 1.00 Page 95 of 115 pages 


The Psion SIBO Hardware Development Kit 


’ 


’ 


OUT: 
Jumps to common exit point 


, 
WriteAndSetAreTheSame: 


Steere Ty 


Ne Ne Ne Ne 


seo 


pushf 

cli 

mov al, cs: [di] .-A4ExifCSChannelSelect 
HwSelectChannel 

push ax 

mov bx, dx 

mov dl, U50UTPUT_LATCH 

mov al, [bx] 

call OutputByte 

pop ax 

HwSelectChannel 

popft 

jmp ExitWithCompletionStatusZero 


ProcEnd noret 


ProcBegin@ A4ExifSense, far 


Reads the state of the LEDS and Switches. 


Psion PLC (c) May 1995 


7Select our SIBO 
; serial channel 
7Store old channel 


;DX (now BX) points 
;to the value to 
output to our 
;peripheral 

;Return old channel 


;To signal completion 


7of set request 


Can be called from PLIB using p_iow(pcb, P_FSENSE, éArgl, &Arg2) 


Where Argl and Arg2 are unsigned bytes. 
In: 


Pointer to control block in applications data space in BX 
Pointer to control block in our CS space in DI 


Al (pointer to Argl) in DX 


Out: 
Jumps to common exit point 
pushf 
cli 
mov al, cs: [di] .-A4ExifCSChannelSelect 
HwSelectChannel 
push ax 
mov bx, dx 
mov dl, U4STATUS_BUFFER 
call InputByte 
mov [bx], al 
mov bx, [si] .RqA2Ptr 
mov dl, U3INPUT_BUFFER 
call InputByte 
mov [bx], al 
pop ax 
HwSelectChannel 
popft 
jmp ExitWithCompletionStatusZero 


ProcEnd noret 


LOCAL DEVICE DRIVER FUNCTIONS 


7Select our SIBO 
;serial channel 
7 Store old channel 


;DX (now BX) points 
;to the variable in 
;which to place the 
;value read from U4. 
7BX now points to 

;the variable in 

;which to place the 
;value read from U3. 


;Return old channel 


;To signal completion 


;of a sense request 


Interrupts must be off prior to the call to this function. 


IN: 


DL has address to which Asic4 is to write 


AL holds the value to output 


mov al, (SerialWriteSingle or A4Address) 


SBUSY 
SCONTOUT 
mov al, dl 
SBUSY 
SDATAOUT 
mov al, (SerialReadSingle or A4Data) 
SBUSY 

SCONTOUT 

SBUSY 

SDATAIN 

ret 

ProcEnd noret 


ProcBegin@ OutputByte 


Interrupts must be off prior to the call to this function. 


Revision 1.00 


Page 96 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


H IN: 
; DL has address to which Asic4 is to write 
; AL has the value to output 


mov al, (SerialWriteSingle or A4Address) 


mov al, dl 


mov al, (SerialWriteSingle or A4Data) 
SBUSY 
SCONTOUT 
SBUSY 
XNOP 
pop ax 
SDATAOUT 
ret 
ProcEnd noret 


ProcBegin@ IntVecO, far 


- Interrupt on serial channel0 
3 Calls Comint with channel control block pointer in DI 
, 

mov di, offset Channel0O 

jmp ComIint 


ProcEnd noret 


if Corporate or S3c 
ProcBegin@ IntVecl1, far 


Sat 


Interrupt on serial channell 


; Calls Comint with channel control block pointer in DI 
, 

mov di, offset Channell 

jmp ComInt 


ProcEnd noret 


ProcBegin@ IntVec2,far 


Interrupt on serial channel2 
Calls Comint with channel control block pointer in DI 


Ne Ne Ne Ne 


mov di, offset Channel2 
7 FALL THROUGH 
ProcEnd noret 
endif 
ProcBegin@ ComInt, far 
, 
; The common interrupt service routine code. 
; When an interrupt occurs, the first task is to read the status 
7 buffer of latch U4. The subsequent action is dependent on the 
; postion of switches Sl and S2. For the purposes of this example, 
; the four posibilities for the switch values correspond somewhat 
; arbitrarily to four different byte values that are written to U5. 
; in the 8086, interrupts cannot occur while in an interrupt routine. 
; If an asynchronous read is pending then the handler is signalled. 
7 IN: 
; Channel's CS based control block pointer in DI 
, 
cmp cs: [di] .A4ExifCSChanReadCompleted, 2 ;Only if 2 do we have 
jne NotAsynchronousRead ;asynch read completed 
mov cs: [di] .A4ExifCSChanReadCompleted, 1 
mov bx, cs: [di] .A4ExifCSProcessId ;Signals completion 
ToSignalByPidNoReSched 7Of read to OS so as 
NotAsynchronousRead: ;to invoke handler 
mov al, cs: [di] .-A4ExifCSChannelSelect 
HwSelectChannel 
push ax 
mov dl, U3INPUT_BUFFER 
call InputByte 
mov cs: [di] .A4ExifCSA2Value, al ;LED byte 
mov dl, U4STATUS_BUFFER 


Revision 1.00 Page 97 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


call InputByte 
mov cs: [di] .A4ExifCSAlValue, al ; Status byte 
and al, INTERRUPT_STATUS_MASK 
xchg al, SwitchStatus 
cmp SwitchStatus, S2S3_ON 7;S2 and S3 on => turn 
je A11LEDsOn 7on alternate LEDs 
cmp SwitchStatus, S2S3_OFF 7S2 and S3 off => not 
je A11LEDsOff ;the alternate LEDs 
cmp SwitchStatus, S2_ONLY 782 on, S3 off => turn 
je TopLEDsOn 7on top four LEDs 
cmp SwitchStatus, S3_ONLY 753 on, S2 off => turn 
je BottomLEDsOn 7on bottom four LEDs 
ErroriInSwitchStatusByte: 
jmp ClearInterruptAndReschedule 
A11LEDsOn: 
mov al, SOME_LEDS_ON 
jmp Output LEDByte 
A11LEDsOff: 
mov al, SOME_LEDS_OFF 
jmp Output LEDByte 
TopLEDsOn: 
mov al, TOP_LEDS_ON 
jmp Output LEDByte 
BottomLEDsOn: 
mov al, BOTTOM_LEDS_ON 
OutputLEDByte: 
mov dl, US50UTPUT_LATCH 
call OutputByte 
ClearInterruptAndReschedule: 
mov dl, INTERRUPT_LATCH 
call OutputByte 
if Asic9 ;A write to this location 
out A9BNonSpecificEoiw, al ;informs the interrupt 
else ;controller that the 
out AlNonSpecificEoi, al ;installed interrupt 
endif ;service routine has 
pop ax ; finished 
HwSelectChannel 
onlkres ;Reschedule if necessary 
ret 
ProcEnd noret 
ProcBegin@ StartInterrupts 
po SSS SES 
; Start interrupts assuming interrupts are 
; off prior to call. 
; The EPOC GenSetRevector service loads in 
; a user-specified interrupt service routine 
; located at the address given in cx:bx 
; (segment cx, offset bx) for the interrupt 
; vector number given in AL. Note that the 
7 variable A4ExifCSChannelIntVec holds the 
; name of the appropriate required interrupt 
; vector routine for the channel. 
H IN: 
; Our CS control block pointer in DI 
H OUT: 
i; Nothing 
is 
mov al, cs: [di] .-A4ExifCSChannelIntNum 7Get the OS to call 
mov cx, CS ;the function in 
push bx 7CS:BX every time 
mov bx, cs: [di] .A4ExifCSChannelIntVec ;that the interrupt 
GenSetRevector ;whose number is in 
pop bx 7;AL occurs 
ife Asic9 
in al, AlInterruptMask 
or al, cs: [di] .A4ExifCSChannelIntMask ;Set the mask 
out AlInterruptMask, al ;location so as 
; interrupt 
else ;to enable that 
in al, A9BInterruptMaskRW ; interrupt 
or al, cs: [di] .A4ExifCSChannelIntMask 
out A9BInterruptMaskRW, al 
endif 
ret 


ProcEnd noret 


Revision 1.00 Page 98 of 115 pages 


The Psion SIBO Hardware Development Kit 


ProcBegin@ StopInterrupts 


; Stop interrupts assuming that interrupts are off 


The EPOC GenResetRevector OS service 


interrupt service routine with the original 
routine and interrupt mask for the vector 
given in AL. 
IN: 

Our CS control block pointer in DI 


Se ee Te 


OUT: 
; Nothing 


ife Asic9 


replaces the previously loaded user-specified 


Psion PLC (c) May 1995 


in al, AlInterruptMask ;Disable the 
mov ah, cs: [di] .A4ExifCSChannelIntMask ; interrupt 
not ah 
and al, ah 
out AlInterruptMask, al 
else 
in al, A9BInterruptMaskRW 
mov ah, cs: [di] .A4ExifCSChannelIntMask 
not ah 
and al, ah 
out A9BInterruptMaskRW, al 
endif 
mov al, cs: [di] .-A4ExifCSChannelIntNum ;Return the interrupt 
GenResetRevector ;vector to the OS 
ret ; default 
ProcEnd noret 
ProcBegin@ StartTheChannelRunning 
Fo eee eeeeeeea= 
; Starts the hardware and interrupts going 
; If the hardware is aready running then there is nothing to do 
; Must check that the hardware has not vanished before restarting it 
H IN: 
; Our CS control block pointer in DI 
7 OUT: 
i Nothing 
7 
pushf 
cli 
cmp byte ptr cs: [di].A4ExifCSChannelRunning, 0 
jne ChannelAlreadyRunning 
call CheckHardwarePresent 
jc HardwareNotPresent 
mov al, cs: [di] .-A4ExifCSChannelSelect 
HwSelectChannel 
push ax 
mov al, (SerialWriteSingle or A4Control) ; Switch on the 
SBUSY output latch U5 
SCONTOUT ;by asserting 
mov al, U5_ENABLE_ON ;the ASIC4 LBO line 
SBUSY ; (LBO is inverted) 
SDATAOUT 
xor ax,ax 
mov dl, INTERRUPT_LATCH 7Clear any pending 
call OutputByte ;interrupt on the 
mov dl, US5OUTPUT_LATCH ;peripheral 
call OutputByte 7Preset the LEDs 
pop ax ;to all off 
HwSelectChannel 
call StartInterrupts 
mov cs: [di] .A4ExifCSChannelRunning, 1 
ChannelAlreadyRunning: 
popft 
cle 
ret 
HardwareNotPresent: 
popft 
stc 
ret 


ProcEnd noret 


ProcBegin@ StopTheChannelRunning 


Revision 1.00 


Page 99 of 115 pages 


The Psion SIBO Hardware Development Kit 


Ne Ne Ne Ne 


Stops the hardware and interrupts 


Psion PLC (c) May 1995 


Checks to see if the hardware is really running to start with 


IN: 
Our CS control block pointer in DI 

i OUT: 
; Nothing 
7 

pushf 

cli 

cmp byte ptr cs:[di].A4ExifCSChannelRunning, 0 

je ChannelNotRunning 

mov al, cs: [di] .-A4ExifCSChannelSelect 

HwSelectChannel 

push ax 

mov al, (SerialWriteSingle or A4Control) 

SBUSY 

SCONTOUT 

mov al, U5_ENABLE_OFF 

SBUSY 

SDATAOUT 

xor ax, ax 

mov dl, US50OUTPUT_LATCH 

call OutputByte 

pop ax 

HwSelectChannel 

call StopInterrupts 

mov cs: [di] .A4ExifCSChannelRunning, 0 
ChannelNotRunning: 

popft 

ret 


Se eT 


ProcEnd noret 


ProcBegin@ CheckHardwarePresent 


Used to determine whether the correct hardware is present 


on the successfully procured serial channel. 


IN: 

CS control block pointer in DI 
OUT: 

Carry clear - correct hardware is there 

Carry set - wrong or no hardware 
pushf 
cli ;Select the correct 
mov al, cs: [di] .A4ExifCSChannelSelect ;SIBO channel that 
HwSelectChannel ;the peripheral is 
push ax ;attached to 
HwNullFrame 
mov al, (SerialSelect or Asic4Id) 
SBUSY ;First look for an 
SCONTOUT 7;ASIC4 at the other 
XNOP ;end of the link 
SBUSY 
SDATAIN ;Ilf the returned 
test al,al ;value is non-zero 
je ConnectionFailedA4NotPresent ;we have an ASIC4 
mov al, (SerialReadSingle or A4InfoR) 
SBUSY ;Now see if we have 
SCONTOUT ;the right peripheral 
XNOP 7;XNOP allows the busy 
SBUSY 7Signal to come 
SDATAIN ;through for the wait 
and al, A4PERIPH_MASK 
cmp al, EXTENDED_INFO_BYTE ;Mask out the bottom 
jne ConnectionFailed ;four bits as the 
pop ax yupper four contain 
HwSelectChannel ;the peripheral ID 
popft 
cle ;If it is our hardware 
ret 7exit with carry clear 

ConnectionFailedA4NotPresent: 

mov al, (SerialSelect or Asic5Normalld) ;Its not an ASIC4 
SBUSY ;peripheral 
SCONTOUT 7By selecting a non 
XNOP 7;ASIC4 as an ASIC4, 
SDATAIN ;we effectively 


test al,al 


Revision 1.00 


;disable whatever is 


Page 100 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


jne ConnectionFailed yout there so we do 
mov al, (SerialSelect or Asic5PackId) ja select for all 
SBUSY ;possibilities so 
SCONTOUT ;that we don't end 
XNOP ;up disabling 
SDATAIN yanything that we 


test al,al ;can't control. 
jne ConnectionFailed 


mov al, (SerialSelect or Asic8Id) 7Modem chip id 

SBUSY 

SCONTOUT 

XNOP 

SDATAIN 
ConnectionFailed: 

pop ax 

HwSelectChannel 

popft 

stc 

ret 

ProcEnd noret 


EndCodeSeg 

stack segment stack para 'data' 
stack ends 

end A4ExifLDD 


Revision 1.00 Page 101 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


SYSS$AS5.ASM 


title ASSPDD Epoc Serial physical device driver for the 16550 
subttl Copyright Psion PLC 1993 
name SYSSAS5 

i VERSION DATE DESCRIPTION 

me MEE ee ee ee eee 

; Lat 08/12/94 Initial version 

7 Written by Jason December 1994 

: Serial Driver for Epoc based around ASIC5 

Sr5s3 = 0 

Sr5S3a = 1 

ifdef BUILDS3 

Sr5S3 = 1. 

Sr5S3a = 0 

BUILDHH equ 1 

endif 

a Sr5S3a 

BUILDSB equ 1 

endif 
include ..\inc\epoc.inc 
include ..\inc\epocser.inc 
include ..\inc\epoclib.inc 
include ..\inc\epocsibo.inc 
include ..\srcs\ossibo.inc 
include ..\srces\ospack.inc 


Sr5ChannelStruct struc 


Sr50pen db ? ; Is the channel open 
SrKSCtY1L db ? ; State of control lines 
Sr5IntVector db 2 ; The Vector number 
Sr5Channel db ? ; Which channel are we 
Sr5Mask db ? ; InterruptMask 
Sr5Running db ; Are we running 
Sr5IntRoutineVec dw cs ; Vector to Interrupt 
Sr5Baud dw ? ; The baud rate 
Sr5LddData dw ? ; Info from Ldd above 
Sr5StatusInt dd ? ; Vectors in serial 
Sr5Recvint dd 2 ; Above to be called 
Sr5XmitInt dd ? ; On input/output 
Sr5ClockEnable db ? ; Reason to stop 

Sr5TheLines db ? ; State of the modem lines 


Sr5ChannelStruct ends 


A5Ent struc 
A5PortA 
A5PortB 
A5PortBMode 
A5PortD 
A5Swipel 
A5Swipe2 
A5IntMask 
A5CtrlReg 
A5USR 
A5RHR 
A5BDLSB 
A5SBDMSB 
A5MCRIEoi 
A5MCRPresentEoi 
A5MCR2Eoi 
ASDUMMYF 

A5Ent ends 


Lt Consumer 
NumberOfChannels 
else 
NumberOfChannels 
endif 
OsActivityMeter 
StopTimeOut 


S_RS2320N 


Revision 1.00 


db 
db 
db 
db 
db 
db 
db 
db 


db 
db 


db 
db 
db 
db 
db 
db 


equ 


equ 


equ 


equ 


equ 


VVV Vv vw 


YN vn vv 


158ch 
1000 


00000001b 


at 


ASIC5 Read/Write 
Port A R/W 

Port B R/W 
Inc/Mode 

Port CD Write only 


Ne Ne Ne Ne Ne 


Interrupt mask R/W 
IntType/Ctrl register 
UART Status/Ctrl 
Receive/Transmit 

Baud Rate write only 
Baud Rate write only 
MCR shift register 
Barcode data&ints 


’ 
’ 


Ne Ne Ne Ne 


; S3 Single Channel 
, HC,S3C Three Channel 


; Activity Channel 
; w~ls (1000ms) wait 


7 RS232 on 


Page 102 of 115 pages 


The Psion SIBO Hardware Development Kit 


Psion PLC (c) May 1995 


S_RSTTLON equ 00000100b ; Line drivers on 
S_CENTON equ 00010000b ; Line drivers enable 
S_RXENB equ 00000001b ; Receive interrupt on 
S_TXENB equ 00000010b ; Transmit interrupt on 
S_TXEMPTY equ 00010000b ; transmit buffer empty 
S_RXINT equ 00000001b ; Receive interrupt? 
S_TXINT equ 00000010b ; transmit interrupt? 
S_MDINT equ 00000100b ; Modem status interrupt 
S_CTS equ 00000001b # CLS 
S_RTS equ 00000010b ; RTS 
S_DCD equ 00000100b DCD 
S_DSR equ 00000010b ; DCR 
S_DTR equ 00000100b ; DIR 
OVERRUN_ERROR equ 01000000b ; Character overrun 
PARITY_ERROR equ 10000000b ; Parity error 
S_PERIPHERALMODE equ 00000011b ; ASIC5 RS232 mode 
S_UART_OFF equ 00000010b ; ASIC5 peripheral mode 
dgroup group stack 
assume ds:dgroup,es:dgroup,ss:dgroup 
CodeSeg 
ProcBegin@ OsAS5PDD 
; SiS SeSe Sees Ses eceses 
dw PDDSignature 
db 'TTY.SR5',0 
dw (VectorEnd-Vector) /2 
Vector: 
dw OsAS5SInstall 
dw OsAS5Remove 
dw OsAS50Open 
dw OsAS5Strategy 
VectorEnd: 


BaudRateTable dw 


-077f£h, -04£fh, -0368h, -02cch, -027£h, -013fh 


dw -009fh, -004fh, -0035h, -0030h, -0027h, -0019h 
dw -—0013h, -000ch, -0009h, -0004h 


DataBitsTable db 0,2,4,6 


’ 


5,6,7,8 bits per char frame 


ParityTable db 08h,18h, 0h, 0h ; Even,Odd,Mark, Space parity 
Chan0O Sr5ChannelStruct <> 
Chanl Sr5ChannelStruct <> 
Chan2 Sr5ChannelStruct <> 


if Consumer 


if Asic9 
SetupTable dw offset AS5Int1l 
db HwIrq2Revector,mask A9MSlave 
db SelectChannel5, (mask A9MClockEnable5 shr 8) 
else 
SetupTable dw offset AS5Intl 
db HwIrq4Revector,mask Asic2Int 
db SelectChannel7, (mask ClockEnable7 shr 8) 
endif 
else 
if Asic9 
SetupTable dw offset AS5Int1l 
db HwIrq4Revector,mask A9MExpIntA 
db SelectChannel3, (mask A9MClockEnable3 shr 8) 
dw offset AS5Int2 
db HwIrq5Revector,mask A9MExpIntB 
db SelectChannel4, (mask A9MClockEnable4 shr 8) 
dw offset ASSInt3 
db HwIrq2Revector,mask A9MSlave 
db SelectChannel5, (mask A9MClockEnable5 shr 8) 
else 
SetupTable dw offset AS5Int1l 
db HwIrq3Revector,mask ExpIntLeftA 
db ExpChannelLeftA, (mask ClockEnableé shr 8) 
dw offset AS5Int2 
db HwIlrq2Revector,mask ExpIntRightB 
db ExpChannelRightB, (mask ClockEnable5 shr 8) 
dw offset AS5Int3 
db HwIrq4Revector,mask Asic2Int 
db SelectChannel7, (mask ClockEnable7 shr 8) 
endif 
endif 


ProcEnd noret 


Revision 1.00 


Page 103 of 115 pages 


The Psion SIBO Hardware Development Kit 


ProcBegin@ OsAS5Install, far 


Install the device driver 
Out: Carry clear -happy to install 


cld 
mov cx, NumberOfChannels 
mov di, offset Chan0od 
mov si, offset SetupTable 
pushf 
cli 
push ds 
mov ax, Cs 
mov ds, ax 
ResetAllChannelsLoop: 
mov di].Sr50pen, 0 
lodsw 
mov di].Sr5IntRoutineVec, ax 
lodsb 
mov di].Sr5IntVector, al 
lodsb 
mov di].Sr5Mask, al 
lodsb 
mov di].Sr5Channel, al 
lodsb 
mov di].Sr5ClockEnable, al 
add di, size Sr5ChannelStruct 
loop ResetAllChannelsLoop 
pop ds 
popft 
AllChannelsOkay: 
cle 
ret 


Mee Ne 


Ne Ne Ne Ne 


GotChan: 


Revision 


ProcEnd noret 


ProcBegin@ OsAS5Remove, far 


Remove the device driver 
Out: Carry clear -happy to remove 


’ 
’ 


~ 


Ne Ne Ne Ne 


Psion PLC (c) May 1995 


Clear the channels 
and set up fixed 
parameters such 

as the interrupt 
vectors and masks 
for each channel 


Channel not open 


Set the interrupt 
handler to call 
hich Interrupt 


= 


Mask for that 
interrupt 

Which Psion serial 
channel 

Baud rate clocking 
enable 


Returns with 
Carry clear 


Carry set -we have an open channel and cant be removed. 


xor ax, ax 
or al, Chan0O.Sr50pen 
or al, Chanl.Sr50pen 
or al, Chan2.Sr50pen 
jz AllChannelsOkay 
mov ax, InUseErr 

stc 

ret 


ProcEnd noret 


ProcBegin@ OsAS5Open, far 


Open a serial channel 


see 


In: SS:SI is a pointer to the open Ent Structure 


Out: Carry clear, control block in BX 


Carry set, error in AX 


cld 

mov si, [si] .OpenNamePtr 
mov al, [sitl] 
CharToFoldedChar 

cmp al, 'A' 

jb ErrorInOpen 

sub al, ‘'A' 

cmp al, NumberOfChannels 
jae ErrorInOpen 

xoOr ah, ah 

mov bx, offset Chan0O 

cmp al, 1 

jb GotChan 

mov bx, offset Chan2 

ja GotChan 

mov bx, offset Chanl 

mov al, 1 

1.00 


If we have a 
channel Still open 
then return a can't 
do error else 
complete okay 


Open the channel 
Get the channel 
Make Upper Case 
Indicator which is 
Part of the name 
Should be A,B,C 


What Channel are 
We Openning 
Pointer to Control 
Block in bx 


Page 104 of 115 pages 


The Psion SIBO Hardware Development Kit 


xchg al, cs: [bx].Sr50Open 
cmp al, 0 
je OkayToOpen 
CantOpen: 
mov ax, InUseErr 
CantOpenDiffErr: 
stc 
ret 
ErroriInOpen: 
mov ax, NameErr 
stc 
ret 
OkayToOpen: 
xor al, al 
mov cs: [bx].Sr5Running, al 
mov cs: [bx].Sr5TheLines, al 
mov cs: [bx].Sr5Ctrl, al 
mov al, cs: [bx].Sr5Mask 
HwGetChannel 
jc CantOpenSoClose 
call CheckHardwarePresent 
jne OpenedOkay 
mov al, cs: [bx].Sr5Mask 
HwF reeChannel 
CantOpenSoClose: 
mov cs: [bx].Sr50pen, 0 
mov ax, DeviceErr 
jmp short CantOpenDiffErr 
OpenedOkay: 
xor ax, ax 
ret 


ProcEnd noret 


AS5StrategyJumpTable label word 


dw offset AS50Open 

dw offset AS5Close 

dw offset AS5Start 
channel 

dw offset AS5Stop 

dw offset AS5Set 

dw offset AS5Sense 

dw offset AS5Control 

dw offset ASS5Enquire 

dw offset AS5Enable 

dw offset AS5SetHandlerCs 


ProcBegin@ OsAS5Strategy, far 


Strategy functions entry point 


Psion PLC (c) May 1995 


7 Now try to Open 
; That channel 


; Check that we have 
; The right Hardware 


Return with the 
Offset of our 
Control Block 
In bx 


Ne Ne Ne Ne 


; Load Handler offsets 
; Close the channel 
; Start the 


7 Stop the channel 
; Does nothing 
; Returns chan status 
; Drive the lines 
; Returns baud rate 
; Begin Output 
; Get Handler segments 


In: vector number in AX + various data in other registers 


; Select the correct 

; Output channel 
Then Call the right 
Function to deal 

; With the strategy 

7; request 


’ 
’ 


; Interrupts off 
;, and flags are on 
; the stack 


7 
7 Warning! This can be called from within Interrupt 
7 
iH DS is OsDataGroup (and MUST be preserved) 
; Out: DI is pointer to control block 
H Old channel and flags on stack 

cld 

mov bx, sp 

mov bx, ss: [bx+4] 

mov bl, cs: [bx].Sr5Channel 

xchg bx, ax 

pushf 

cli 

HwSelectChannel 

mov ah, bh 

xOr bh, bh 

push ax 

mov ax, di 

mov di, sp 

mov di, ss: [dit+8] 

jmp AS5StrategyJumpTable [bx] 


ProcEnd noret 


ProcBegin@ AS5Open, far 


; Old channel and flags on the stack, 
mov cs: [di].Sr5LddData, cx 
mov word ptr cs: [di].Sr5StatusInt, 


Revision 1.00 


interrupts off 


; Load the offsets of 


ax ; the data send and 


Page 105 of 115 pages 


The Psion SIBO Hardware Development Kit 


if 


else 


endif 


mov word ptr cs:[di].Sr5RecvInt, si 
mov word ptr cs:[di].Sr5XmitInt, dx 
xor ax, ax 

pop ax 

HwSelectChannel 

popft 

ret 


ProcEnd noret 


ProcBegin@ AS5Close, far 


Old channel and flags on the stack, 


and cs:[di].Sr50Open, 0 
mov al, cs: [di].Sr5Mask 
HwF reeChannel 

pop ax 

HwSelectChannel 

popft 

ret 


ProcEnd noret 


ProcBegin@ AS5Start, far 


Old channel and flags on the stack, 


call CheckHardwareFromStart 

mov dx, 0 

je CantStartSomethingWhichIsntThere 
Asic9 

in ax, AQWControlExtraRW 

or ah, cs: [di].Sr5ClockEnable 

out A9QWControlExtraRW, ax 

mov al, cs: [di].Sr5ClockEnable 
HwSetA2Control2Bits 

mov al, SerialWriteSingle or A5USR 
SBUSY 

SCONTOUT 

mov al, cs: [di].Sr5Ctrl 

SBUSY 

SDATAOUT 

mov al, SerialWriteSingle or A5BDLSB 
SBUSY 

SCONTOUT 

mov al, byte ptr cs: [di].Sr5Baud 
SBUSY 

SDATAOUT 

mov al, SerialWriteSingle or A5BDMSB 
SBUSY 

SCONTOUT 

mov al, byte ptr cs: [dit+1].Sr5Baud 
SBUSY 

SDATAOUT 

call Get TheInterrupt 

xor CX), Cx 

call DriveRts 

mov al, SerialWriteSingle or A5CtrlReg 
SBUSY 

SCONTOUT 

mov al, (S_CENTON or S_RS2320N or 
SBUSY 

SDATAOUT 

mov cx, 8 ; 8 ms 

pop dx 

call WaitTimer 

push dx 

mov ah, (S_RXENB or S_TXENB or S_MDINT) 
call EnableTheInterrupt 

mov cs:[di].Sr5Running, 1 

mov bx, Asic5SerialCurrent 
HwSetPCurrent 

call Status 


Revision 1.00 


interrupts 


Psion PLC (c) May 1995 


; veceive routines in 
; the Ldd above us 
; DX=0 —-We don't support 
7; power management 
; Return the old 
; Channel 


interrupts off 


; Close the Channel 

; Free up our channel 
; And the Hardware 

; Channel 

; Return the old 

; channel 


off 


; Start the S3s clock 
; Generator 


; Set the baud rate 
; and other 
; Characteristics 


Get the interrupt 
and clear down 

the RTS line (DTR 
stays at the state 
; it was set) 


’ 
’ 


’ 
’ 


S_RSTTLON) 


; Switch on the line 
; QGrivers and wait 
; for them to power up 


; Start all interrupts 


Page 106 of 115 pages 


The Psion SIBO Hardware Development Kit 


CantStartSomethingWhichIsntThere: 


pop ax 
HwSelectChannel 
popft 
ret 


ProcEnd noret 


ProcBegin@ AS5Stop, far 


Psion PLC (c) May 1995 


; Return the old 
; Channel 


; Old channel and flags on the stack, interrupts off 
xor CX, CX ; Clear the state of 
call DriveRts ; the modem lines 
mov al, SerialReadSingle or A5IntMask ; Stop all of the 
SBUSY ; interrupts 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
and al, not (S_TXENB or S_RXENB or S_MDINT) 
mov ah, al 
mov al, SerialWriteSingle or A5IntMask 
SBUSY 
SCONTOUT 
mov al, ah 
SBUSY 
SDATAOUT 
pop ax 
cmp dh, DevHoldPowerFail 
je Dont StopHardware 
cmp cs:[di].Sr5Running, 1 
jne DontWait 
mov cx, StopTimeOut 
jmp short CompareNow 
WaitForEmpty: 
call TickTimer 
CompareNow: 
mov al, SerialReadSingle or A5USR 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
test al, S_TXEMPTY 
loopne WaitForEmpty 
DontWait: 
cmp bh, DevHoldNormal 
je Dont StopHardware 
if Asic9 
mov cl, cs: [di].Sr5ClockEnable ; Turn off baud rate 
not cl ; Clocking from the 
in ax, A9WControlExtraRW } S3y3a 
and ah, cl 
out A9WControlExtraRW, ax 
else 
mov al, cs: [di].Sr5ClockEnable 
HwClearA2Control2Bits 
endif 
mov al, SerialWriteSingle or A5CtrlReg ; Stop the drivers 
SBUSY , and stuff 
SCONTOUT 
sub al, al ; Clear S_CENTON, 
SBUSY 7 S_RS2320N, S_RSTTLON 
SDATAOUT 
Dont StopHardware: 
mov al, dl ; Return the old 
HwSelectChannel ; Channel 
popft 
xor bx, bx 
HwSetPCurrent 
ret 
ProcEnd noret 
ProcBegin@ AS5Set, far 
; Se SeSeees ees Sees 
; Old channel and flags on the stack, interrupts off 


Revision 1.00 


Page 107 of 115 pages 


The Psion SIBO Hardware Development Kit 


; In: Information required is on the stack 
pop ax 
HwSelectChannel 
popft 
mov ah, ss:[si].SerialCharTbaud 
cmp ah, ss: [si] .SerialCharRbaud 
jnz ErrorInSet 
cmp ah, P_BAUD_50 
jb ErroriInSet 
cmp ah, P_BAUD_19200 
ja ErroriInSet 
Got TheSpecialBaud: 
dec ah 
mov cl, ss:[si].SerialCharFrame 
mov al, ss:[si].SerialCharParity 
dec al 
xor ch, ch 
push bx 
test cl, P_TWOSTOP 
jz OnlyOneStopBit 
or ch, 020h 
OnlyOneStopBit: 
test cl, P_PARITY 
jz NoParity 
mov bx, offset ParityTable 
xlat cs: [ParityTable] 
or ch, al 
NoParity: 
mov bx, offset DataBitsTable 
and cl, P_DATA_FRM 
mov al, cl 
xlat cs: [DataBitsTable] 
Or ch, al 
mov bx, offset BaudRateTable 
mov al, ah 
xOr ah, ah 
shl ax, 1 
add bx, ax 
mov ax, cs: [bx] 
pop bx 
mov es? [dt] .Sractrl; ch 
mov cs:[di].Sr5Baud, ax 
xOr al, al 
ret 
ErroriInSet: 
mov al, NotSupportedErr 
stc 
ret 


ProcEnd noret 


ProcBegin@ AS5Sense, far 


seo 


’ 


’ 


’ 


’ 


~ 


Psion PLC (c) May 1995 


Return the old 
channel 


Set the Recieve, 
Transmit characteristics 
First set the Baud 

Rate 


Then the number of 
Stop bits 


The Parity 


And finally the 
Number of data bits 
Per frame 


; Old channel and flags on the stack, interrupts off 
; Out: The state of the DCD,CTS,DSR lines returned in DX 
call Status 
pop ax ; Return the old 
HwSelectChannel ; Channel 
popft 
ret 


ProcEnd noret 


ProcBegin@ Status 


i Out: State of modem lines in DX 
mov al, SerialReadSingle or A5USR 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
and al, (S_CTS or S_DSR or S_DCD) 
xor al, (S_CTS or S_DSR or S_DCD) 
xOr ah, ah 


Revision 1.00 


see 


Get the current 
Modem status 
Lines and return 
With the result 
In dx 


Get the lines we want 
Invert signals 


Page 108 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


mov ax, ax 
ret 
ProcEnd noret 


ProcBegin@ AS5Control, far 


; Old channel and flags on the stack, interrupts off 

7 In: Lines to drive and state to drive them in DX 
mov onl emo ie ; Set the state of one 
test dh, P_SRCTRL_DTR ; of the modem Lines 
jz DriveRtsNow ; DH is the line to 
call DriveDtr ; Drive and DL is the 
pop ax ; Stateto drive it to 
HwSelectChannel ; Return the old 
popft ; channel 
ret 

DriveRtsNow: 
call DriveRts 
pop ax ; Return the old 
HwSelectChannel ; channel 
popft 
ret 


ProcEnd noret 


ProcBegin@ DriveDtr 


mov ah, S_DTR ; Set/Reset the DTR 
jmp short DriveTheLine ; Line 
ProcEnd noret 


ProcBegin@ DriveRts 


mov ah, S_RTS ; Set/Reset RTS 
DriveTheLine: 
mov al, SerialWriteSingle or A5PortD ; Common code to set 
SBUSY ; and reset either 
SCONTOUT ; line while 
mov al, cs:[di].Sr5TheLines ; preserving the 
test cl, cl ; states of the other 
IZ ClearLine ; lines 
or al, ah 
jmp DoTheOutput 
ClearLine: 
not ah 
and al, ah 
DoTheOutput: 
mov cs:[di].Sr5TheLines, al 
SBUSY 
SDATAOUT 
ret 


ProcEnd noret 


ProcBegin@ AS5Enquire, far 


7 Old channel and flags on the stack, interrupts off 
- Out: DX,AX are the supported baud rates AX for 50 to 19200 DX for above 
; CX says what data bits, parity, etc we support 
pop ax ; Return the old 
HwSelectChannel ; Channel 
popf 
if Asic9 
mov ax, —-1 
else 
mov ax, O7fffh 
endif 
xor dx, ax 
mov cx, (Offffh AND (NOT (P_SRINQ_SPLIT OR P_SRINQ_PARSPACE OR 
P_SRINQ_PARMARK) ) ) 
ret 


ProcEnd noret 


ProcBegin@ AS5Enable, far 


Revision 1.00 Page 109 of 115 pages 


The Psion SIBO Hardware Development Kit 


Psion PLC (c) May 1995 


- Old channel and flags on the stack, interrupts off 
mov ah, S_TXENB ; Begin Output by 
call EnableTheInterrupt ; enabling transmit 
pop ax ; interrupts 
HwSelectChannel ; Return the old 
popft ; channel 
ret 


ProcEnd noret 


ProcBegin@ AS5SetHandlerCs, far 


CX is CS of above LDD 


sew 


mov word ptr cs: [di]. (Sr5StatusInt+2), cx 
mov word ptr cs:[di].(Sr5RecvInt+2), cx 
mov word ptr cs: [di]. (Sr5XmitInt+2), cx 
pop ax 

HwSelectChannel 

popft 

ret 


ProcEnd noret 


ProcBegin@ AS5Int3, far 


mov di, offset Chan2 
mov ax, PortCActive 
jmp ComInt 


ProcEnd noret 


ProcBegin@ AS5Int2,far 


mov di, offset Chanl 
mov ax, PortBActive 
jmp ComIint 


ProcEnd noret 


ProcBegin@ AS5Int1,far 


mov di,offset Chan0 
mov ax, PortAActive 
4 FALL THROUGH 


ProcEnd noret 


ProcBegin@ ComInt, far 


The common interrupt handler 
DS points to OS data space 
DI is our control block 


Mee Ne 


; AX is the Active channel 
ab S3b or S3c 

or ds: [OsActivityMeter], ax 
endif 

mov al, cs: [di].Sr5Channel 

HwSelectChannel 

push ax 

mov bx, cs: [di].Sr5LddData 
TheInterruptLoop: 

mov al, SerialReadSingle or A5CtrlReg 

SBUSY 

SCONTOUT 

XNOP 

SBUSY 

SDATAIN 

test al, al 

je NothingToDo 
HaveWeGotAModemStatusLineInterrupt: 

test al, S_MDINT 

4z HaveWeGotARecievelInterrupt 

mov al, SerialReadSingle or A5USR 

SBUSY 

SCONTOUT 


Revision 1.00 


~ 


Mee Ne 


Old channel and flags on the stack, interrupts off 


; Load the Segment 

; Within which the 
The Ldd above us 
Return the old 
channel 

; Resides 


Channel 3 interrupt 
vector 
Jumps to Comint 


see 


~ 


Channel 2 interrupt 
vector 
Jumps to Comint 


seo 


~ 


Channel 1 interrupt 
7; vector 

; Falls through 

7 to Comint 


; Set active state 


; Select our 
; Channel 


; Data for LDD above 
; in bx 

; Find out what 

; caused the 

; interrupt 


Page 110 of 115 pages 


The Psion SIBO Hardware Development Kit 


Psion PLC (c) May 1995 


; Something has been 
; recieved in error 


; Establish the error 


; Get the character 
; in question 


; invert signals 


XNOP 
SBUSY 
SDATAIN 
test al, (OVERRUN_ERROR or PARITY_ERROR) 
jz ModemStatusInterruptOnly 
push ax 
mov ah, SERPARITY_ERR 
test al, PARITY_ERROR 
jnz IsAParityError 
mov ah, SEROVERRUN_ERR 
IsAParityError: 
mov al, SerialReadSingle or A5RHR 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
push di 
call dword ptr cs: [di] .Sr5RecvInt 
pop di 
pop ax 
ModemStatusInterruptOnly: 
and ax, (S_CTS or S_DSR or S_DCD) 
xor al, (S_CTS or S_DSR or S_DCD) 
mov ax, ax 
push di 
call dword ptr cs: [di].Sr5StatusInt 
pop di 
jmp short TheInterruptLoop 


HaveWeGotARecievelInterrupt: 


; AX has character received 


Resced if neccessary 


; Gisable TX interrupts 


test al, S_RXINT 
jz HaveWeGotATransmitInterrupt 
mov al, SerialReadSingle or A5RHR 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
xOr ah, ah 
push di 
call dword ptr cs: [di] .Sr5RecvInt 
pop di 
jmp short TheInterruptLoop 
HaveWeGotATransmitInterrupt: 
test al, S_TXINT 
jz NothingToDo 
push di 
call dword ptr cs: [di] .Sr5XmitInt 
pop di 
test ax, ax ; —-l1 if disable 
js DisableTransmitInts 
mov ah, al 
mov al, SerialWriteSingle or A5RHR 
SBUSY 
SCONTOUT 
mov al, ah 
SBUSY 
SDATAOUT 
jmp TheInterrupt Loop 
NothingToDo: 
if Asic9 
out A9BNonSpecificEoiwW, al 
else 
out AlNonSpecificEoi, al 
endif 
pop ax 
HwSelectChannel 
cle ; 
ret 
DisableTransmitInts: 
mov al, SerialReadSingle or A5IntMask 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
and al, not S_TXENB 
mov ah, al 
mov al, SerialWriteSingle or A5IntMask 
SBUSY 


Revision 1.00 


Page 111 of 115 pages 


The Psion SIBO Hardware Development Kit 


SCONTOUT 
mov 
SBUSY 
SDATAOUT 
jmp TheInterrupt Loop 
ProcEnd noret 


al, ah 


ProcBegin@ GetTheInterrupt 


mov al, cs:[di].Sr5IntVector H 
mov Cx, CS F 
mov bx, cs:[di].Sr5IntRoutineVec ; 
GenSetRevector A 
ret , 


ProcEnd noret 


ProcBegin@ EnableTheInterrupt 


mov al, SerialReadSingle or A5IntMask 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
or ah, al 
mov al, SerialWriteSingle or A5IntMask 
SBUSY 
SCONTOUT 
mov al, ah 
SBUSY 
SDATAOUT 
if Asic9 
in al, A9BInterruptMaskRW ; 
or al, cs: [di].Sr5Mask ; 
out A9BInterruptMaskRwW, al 
else 
in al, AlInterruptMask 
or al, cs: [di] .Sr5Mask 
out AlInterruptMask, al 
endif 
ret 
ProcEnd noret 
ProcBegin@ StopInterrupts 
; StessSeSesee—e-Seeeseeese 
mov al, SerialReadSingle or A5IntMask H 
SBUSY ; 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
and al, not (S_RXENB or S_TXENB or S_MDINT) 
mov ah, al 
mov al, SerialWriteSingle or A5IntMask 
SBUSY 
SCONTOUT 
mov al, ah 
SBUSY 
SDATAOUT 
mov ah, cs: [di].Sr5Mask 
not ah 
if Asic9 
in al, A9BInterruptMaskRW ; 
and al,ah ; 
out A9BInterruptMaskRW, al ; 
else ; 
in al, AlInterruptMask 
and al,ah 
out AlInterruptMask, al 
endif 
mov al, cs:[di].Sr5IntVector 
GenResetRevector 
ret 


Revision 1.00 


Psion PLC (c) May 1995 


Load the address of 
the appropriate 
interrupt routine 
into the correct 
vector 


Set the mask 
to enable Interrupts 


Stop interrupts 
from Asic5 


Stop Interrupts 
By clearing the 


Mask and resetting 
The Vector 


Page 112 of 115 pages 


The Psion SIBO Hardware Development Kit 


ProcEnd noret 


ProcBegin@ CheckHardwarePresent 


mov al, cs: [bx] .Sr5Channel 
HwSelectChannel 
HwNullFrame 
mov al, (SerialSelect or Asic5Normalld) 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
test al,al 
je ConnectionFailed 
GotConnection: 
popft 
ous) 
ret 
ConnectionFailed: 
mov al, 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
test 
jne 
mov 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
test 
jne 
mov 
SBUSY 
SCONTOUT 
XNOP 
SBUSY 
SDATAIN 
ConnectionFailedExit: 
popft 
stc 
ret 
ProcEnd noret 


SerialSelect or Asic4Id 


al, al 
ConnectionFailedExit 
al, SerialSelect or Asic8Id 


al, al 
ConnectionFailedExit 
al, SerialSelect or Asic5PackId 


ProcBegin@ CheckHardwareFromStart 


pushf 

HwNullFrame 

mov al, (SerialSelect or Asic5Normalld) 
SBUSY 

SCONTOUT 

XNOP 

SBUSY 

SDATAIN 

test al,al 

je ConnectionFailed 

test al, mask A5MultiDrop 

jne ConnectionFailedExit 

popft 
mov 
SBUSY 
SCONTOUT 
mov 
SBUSY 
SDATAOUT 
cle 

ret 
ProcEnd noret 


al, 


al, S_PERIPHERALMODE 


ProcBegin@ WaitTimer 


Revision 1.00 


SerialWriteSingle or A5PortBMode 


Ne Ne Ne Ne te 


Ne Ne Ne Ne Ne 


’ 


Psion PLC (c) May 1995 


Check that the 
; Harware is there 


And that it is what 
It should be 

First look for An 
ASIC4 at the other 
End of the link 


’ 


’ 


’ 


Asic4 Id 


Modem chip Id 


Asic5Spack Id 


Check that the 
Harware is there 
First look for An 
ASIC5 at the other 
End of the link 


’ 
’ 
’ 


If not a 3link or 
if in multidrop 
mode then we are 
in trouble 


Put the 3Link in 
peripheral mode 


Page 113 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


In: CX number of ms to wait for 
Channel store in DL 
Out: Channel store in DL 


Wait for a given 


inc cx i 

WaitTickLoop: ; Number of ms 
call TickTimer ; Plus one to guarantee 
loop WaitTickLoop ; That at least cx ms 
ret 7 Go by 
ProcEnd 


WaiterLoop: 


stack 
stack 


ProcBegin@ TickTimer 


Uses writes down our channel to simulate tick timer waits 

Must allow interrupts so other things can run -we will be here 
for 1/1000 of a second and may be called many times 
ChannelStore in/out in DL 


mov al, dl ; Return the old 
HwSelectChannel ; Channel 

mov ah, al 
pushf 

sez 

push Cx 

mov cx, 12 ims 

128 frames =1lms 

pushf about 12 times 

cli 7 round the loop 

out ResetWatchDog, al 

mov al, ah 

HwSelectChannel 

mov dl, al ; Get Correct channel 
mov al, (SerialWriteSingle or 0) Do a write to 

SBUSY nowhere and 

SCONTOUT waste some time 


See Ne 


See Ne 


SCONTOUT ; Do it eight times 


SBUSY 
SCONTOUT 
SBUSY 
mov al, dl 
HwSelectChannel 
mov ah, al 
popft 

loop WaiterLoop 
pop CX 

popft 

mov al, ah 
HwSelectChannel 
mov dl, al 
ret 

ProcEnd 


Return the old 
channel 


’ 
’ 


EndCodeSeg 


segment stack para 'data' 
ends 


end OsAS5PDD 


Revision 1.00 Page 114 of 115 pages 


The Psion SIBO Hardware Development Kit Psion PLC (c) May 1995 


Assembler Macros 


Excerpts from the include file ossibo.inc. 


if ASIC1 
SCONTOUT macro 
out A2SerialControl, al 
endm 
SDATAOUT macro 
out A2SerialData, al 
endm 
SBUSY macro 
wait 
endm 
SREAD macro _REG 
mov al, SerialReadSingle or _REG 
out A2SerialControl, al 
nop 
SBUSY 
in al, A2SerialData 
endm 
SREADM macro _REG 
mov al, SerialReadMulti or _REG 
out A2SerialControl, al 
nop 
SBUSY 
in al, A2SerialData 
endm 
SWRITE macro _REG,_VAL 
mov al, SerialWriteSingle or _REG 
out A2SerialControl, al 
SBUSY 
mov al, _VAL 
out A2SerialData, al 
endm 
SWRITEM macro _REG,_VAL 
mov al, SerialWriteMulti, _REG 
out A2SerialControl, al 
SBUSY 
mov al, _VAL 
out A2SerialData, al 
endm 
endif 
ach ASIC9 
SCONTOUT macro 
out A9BSerialControlW, al 
endm 
SDATAOUT macro 
out A9BSerialDataRW, al 
endm 
SDATAIN macro 
in al, A9BSerialDataRW 
endm 
SBUSY macro 
endm 
SREAD macro _REG 
mov al, SerialReadSingle or _REG 
out A9BSerialControlwW, al 
in al, A9BSerialDataRW 
endm 
SREADM macro _REG 
mov al, SerialReadMulti or _REG 
out A9BSerialControlwW, al 
in al, A9BSerialDataRW 
endm 
SWRITE macro _REG,_VAL 
mov al, SerialWriteSingle or _REG 
out A9BSerialControlwW, al 
mov al, _VAL 
out A9BSerialDataRW, al 
endm 
SWRITEM macro _REG,_VAL 
mov al, SerialWriteMulti or _REG 
out A9BSerialControlwW, al 
mov al, _VAL 
out A9BSerialDataRW, al 
endm 
endif 


Revision 1.00 Page 115 of 115 pages 


